Ravi Sankar Samanthapudi

Hi all,

I am trying to execute .exe file on device from PC. Everything works fine, but is there any way that I can wait for the remote process to complete.

I think, WaitForSingleObject does not solve my problem as I need to wait for the process that is running remotely.

Public Class CeRAPI

<DllImport("rapi.dll", CharSet:=CharSet.Unicode)> _

Private Shared Function GetLastError() As Integer

End Function

<DllImport("rapi.dll", CharSet:=CharSet.Unicode)> _

Private Shared Function CeCreateProcess(ByVal Filename As String, ByVal param As String, ByVal procAttr As Integer, ByVal threadAttr As Integer, ByVal boolh As Integer, _

ByVal creFlags As Integer, ByVal env As Integer, ByVal curDir As String, ByVal si As Integer, ByRef pi As PROCESSINFO) As Integer

End Function

<DllImport("rapi.dll", CharSet:=CharSet.Unicode)> _

Private Shared Function CeRapiInit() As Integer

End Function

<StructLayout(LayoutKind.Sequential)> _

Public Structure PROCESSINFO

Public hProcess As IntPtr

Public hThread As IntPtr

Public dwProcessId As IntPtr

Public dwThreadId As IntPtr

End Structure

<DllImport("rapi.dll", CharSet:=CharSet.Unicode)> _

Private Shared Function CeRapiUninit() As Integer

End Function

Public Shared Function RunCEProgram(ByVal fileName As String, Optional ByVal CmdLine As String = "") As Boolean

Dim pi As PROCESSINFO

Dim i As Integer

CeRapiInit()

If CmdLine = String.Empty Then

i = CeCreateProcess(fileName, Nothing, 0, 0, 0, 0, 0, Nothing, 0, pi)

'I would like to wait here untill above process terminates successfully

Else

'use a command line

i = CeCreateProcess(fileName, CmdLine, 0, 0, 0, 0, 0, Nothing, 0, pi)

End If

CeRapiUninit()

If (i = 0) Then

Return True

Else

Return False

End If

End Function

End Class

Any help is greatly appreciated,

thanks

Ravi


Re: Smart Devices General Wait for CECreateProcess complete

Christopher Fairbairn

Hi,

I am not aware of a neat solution here (i.e. would love to be proved wrong).

To my knowledge the handles returned by CeCreateProcess can not be used by desktop APIs.

In the past I have worked around this issue by using more advanced functionality of the RAPI API.

What I did was write a small DLL designed to run on the PDA. Within this DLL I exposed a function which would launch a process and then wait for it to exit. Using the CeRapiInvoke function (http://msdn2.microsoft.com/en-us/library/ms913936.aspx) enabled me to execute this function directly on the PDA from my desktop application.

In my case I didn't mind doing this as I was already using the DLL for other tasks, so it didn't add much complexity. However it does require writing a smart device DLL (which probably needs to be done in C), and in many recent PDAs could lead to difficulty due to security restrictions which restrict which DLLs can be invoked in this manor by default.

Hope this helps,

Christopher Fairbairn

PS: From your code sample it seems you are wrapping up the RAPI API with PInvokes from VB.NET. Are you aware of the free OpenNETCF Desktop Communication library available from http://www.opennetcf.com/sharedsource/communication.ocf This library has the large majority of the RAPI API already wrapped up into an assembly you could simply reference from your VB.NET application.






Re: Smart Devices General Wait for CECreateProcess complete

Ravi Sankar Samanthapudi

Thanks for your time, I was looking at the msdn samples from http://msdn2.microsoft.com/en-us/library/aa446531.aspx and they got this working by the dll written in C.

InvokeCab(

MSIHANDLE hInstall,

PMSIHANDLE hProgressRec,

HANDLE heCancel,

WCHAR *pwzFile,

WCHAR *pwzPath,

WCHAR *pwzHelperDll)

{

_RESULT result = rDeployFailure;

WCHAR buf[256];

wcscpy(buf, L"Invoking ");

wcscat(buf, pwzFile);

wcscat(buf, L" on the device\n");

wcscat(buf, L"Please check device for further instructions.");

ActionDataW(hInstall, buf);

PROCESS_INFORMATION pi;

memset(&pi, 0, sizeof(pi));

if (CeCreateProcess(L"wceload.exe",

pwzPath,

NULL,

NULL,

FALSE,

0,

NULL,

NULL,

NULL,

&pi)) {

for (;Wink {

DWORD wait = WaitForSingleObject(heCancel, 1000);

if (wait==0) {

result = rDeployFailure;

break;

}

/* We can't wait on the handle returned from

* CeCreateProcess, so we poll the device to see if

* is still active or has completed.

*/

BYTE *pData = NULL;

DWORD dwBytes = 4;

HRESULT hResult = CeRapiInvoke(pwzHelperDll,

L"IsProcessComplete",

sizeof(pi.hProcess),

(BYTE*)&pi.hProcess,

&dwBytes,

&pData,

NULL, NULL);

if (pData) {

if (*(DWORD*)pData) {

result = rSuccess;

LocalFree(pData);

break;

}

LocalFree(pData);

}

}

CeCloseHandle(pi.hThread);

CeCloseHandle(pi.hProcess);

}

MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hProgressRec);

return result;

}

But I dont want to waste time spending on this code, rather I would like to try it your way. BTW, I am using OpenNetCF.Desktop.Communications library, it got very cool stuff that I dont need to worry about the unmanaged code.

thanks a lot,

ravi.






Re: Smart Devices General Wait for CECreateProcess complete

Christopher Fairbairn

Hi Ravi,

Ravi Sankar Samanthapudi wrote:
But I dont want to waste time spending on this code, rather I would like to try it your way

Their way is the same way that I suggested (or a slight variant of) so I am not too sure what you mean by "wasting time spending on this code".

In their example source code they have a function called IsProcessComplete which lives in a DLL that is placed on the PDA.

They use CeCreateProcess to start an executable remotely on the PDA and then use CeRapiInvoke to call their IsProcessComplete function to wait for the process to exit.

In my approach I simply combined both calls into a function called RunExecutable which lives within the DLL. I then use CeRapiInvoke to execute this function passing in the executable name.

The only difference between the two approachs is which side (PDA or Desktop) causes the executable to start execution.

If you can adopt their sample code to perform your task, that is possibly the best approach.

If using this approach it would be wise to read the security related comments at the bottom of the MSDN documentation for CeRapiInvoke - http://msdn2.microsoft.com/En-US/library/aa454605.aspx. In particular the bit which starts with

These devices are considered "Locked," which prevents you from using CeRapiInvoke to invoke device-side DLLs unless you take extra steps to satisfy the requirements of the Remote Access Security Policy

Hope this helps,

Christopher Fairbairn