Welcome to MSDN Blogs Sign in | Join | Help

Visual Studio For Devices

A Team blog from the Visual Studio for Devices Team
CoreCon API - Part V

Last post we looked at how to write a device side agent. I am uploading the source for file viewer written using CoreCon API's.

How to use

  • You need to have visual studio 2008 installed in your machine.
  • Extract the zip file. It has 2 solutions and 2 xsl files.
  • Take a back up of your global datastore directory
    • In vista this is "C:\Users\All Users\Microsoft\corecon\1.0"
    • In non-vista this is  "c:\documents and settings\All users\Application Data\Microsoft\corecon\1.0"
  • Copy the xsl files to "addons" directory inside the Global datastore directory.
  • Build the solutions. Copy the RemoteAgent.exe to d:\temp\Armv4i directory. If you are keeping the file in different directory then you need to modify the RemoteAgent.xsl file accordingly (modify the RootPath property)
  • Execute the FileViewer.exe - you have the fileviewer ready.

I have created the RemoteAgent.xsl package for Armv4i architecture only. If you want to work in any other architecture then you need to build the RemoteAgen.sln in the required architecture. Add a Packagetype entry in the Remoteagent.xsl for that architecture. In case you want to add support for X86, then add the following inside the Packagetypecontainer (in RemoteAgent.xsl)

<PACKAGETYPE Name="x86" ID="x86" Protected="True">
  <PROPERTYCONTAINER>
    <PROPERTY ID="RemotePath" Protected="True">%CSIDL_WINDOWS%</PROPERTY>
    <PROPERTY ID="RootPath" Protected="True">D:\temp\x86</PROPERTY>
    <PROPERTY ID="CommandLine" Protected="True"></PROPERTY>
    <PROPERTY ID="CPU" Protected="True">x86</PROPERTY>
    <PROPERTY ID="Host" Protected="True">RemoteAgent.exe</PROPERTY>
  </PROPERTYCONTAINER>
  <FILECONTAINER>
    <FILE ID="RemoteAgent.exe" />
  </FILECONTAINER>
</PACKAGETYPE>

Place the remoteagent.exe built for X86 in D:\temp\X86 directory.

--

Anand R

Posted Thursday, December 06, 2007 5:00 AM by MobileDevGroup | 4 Comments

Filed under:

Attachment(s): fileviewer.zip

CoreCon API - Part IV

In the last post we saw how to create a package and use that for downloading set of files.

Writing Device Agent

What do I get if I write an my own agent?

  • You can reliably start your agent. When the start call is completed you are guaranteed that your agent has started running in device.
  • You can create stream independent of the underlying transport mechanism. You need not worry about whether DMA or TCP is the underlying transport.
    • You can use the streams for your device-desktop interaction
  • You need not worry about serializing and de-serializing the data you send.
    • We provide a packet class which could be used to send and receive most of the basic data types.

Let’s see how we can write a device agent.

When an agent is started in device, it should call ‘AcknowledgeLaunch’.

Calling AcknowledgeLaunch signifies 2 things.

  • Agent conveys that it has done with all its initialization and ready to accept connections from desktop
  • It also registers the set of Ids that will be used to create streams.

Here is the code snippet to do AcknowledgeLaunch

HRESULT (*pfnGetDeviceService)(IDeviceAgentTransport**);

hMod = ::LoadLibrary(L "DeviceAgentTransport.dll");

if(hMod == NULL)

{

//Error Handle…

}

pfnGetDeviceService = (GetDeviceAgentTransportFunction) ::GetProcAddress(hMod,L"GetDeviceAgentTransport");

if( NULL == pfnGetDeviceService)

{

//Error Handle…

}

hr = pfnGetDeviceService(out_pTransport);

if(FAILED(hr))

{

//Error Handle…

}

//We got the DeviceAgentTransport. Call acknowledgelaunch to indicate all initializations are done.

hr = out_pService->AcknowledgeLaunch(count,lpServiceIds);

if(FAILED(hr))

{

//Error Handle…

}

Now, the Device agent is ready to accept connections…

IDevicePacketStream* out_pStream;

out_pService ->AcceptConnectionEx(lpServiceId ,&out_pStream);

AcceptConnectionEx is analogous to TCP accept call. This is a blocking call and will wait till a Connect (CreatePackaetStream) call is made from desktop with the same serviced. Note that this serviced has to be one among the registered service Ids (in AcknowledgeLaunch).

Send receive Packets

Let’s send some packets to desktop.

We need to create a packet, write the info into the packet and send the packet in stream.

GetNewPacketFunc packFunc;

HINSTANCE hMod = ::LoadLibrary(L "DeviceAgentTransport.dll");

packFunc = (GetNewPacketFunc) ::GetProcAddress(hMod, L"GetNewPacket");

if( NULL == packFunc)

{

//Error Handle…

}

IPacket *writePacket;

packFunc(&writePacket);

writePacket->WriteString(szSendString); //Some string to be sent to desktop

out_pStream->write(writePacket);

Just like in TCP, Read is a blocking call. Below call will wait till some data is sent from the desktop.

IPacket *packet;

packFunc (&packet);

hr =out_pStream->Read(&packet);

Desktop Side

So far we are discussing about how the device agent will look like. We will look at the desktop counterpart for this.

//PackageId is the Guid corresponding to the package we want to deploy

RemoteAgent mRemoteAgent = Device.GetRemoteAgent(new ObjectId(packageID));

//This will start the agent. This call will be blocked till AcknowledgeLaunch is called in device side.

mRemoteAgent.Start(“”);

//This is the connect call. 

//This will unblock the AcceptConnectionExe in device

DevicePAcketStream mStream = mRemoteAgent.CreatePacketStream(streamId);

Packet pkt = new Packet();

Pkt.WriteString(“hai”);

mStream.write(pkt);

pkt = mStream.Read();

string msg = pkt.ReadString();

Below is the sequence diagram for the desktop and device interaction

CoreCon Timeline

In next post we will look at actual File Viewer written using CoreCon API's.

--

Anand R

Posted Monday, December 03, 2007 11:18 AM by MobileDevGroup | 2 Comments

Filed under:

CoreCon API – Part III

Package

More than often we would like to deploy multiple files as part of our application. Also these files might vary depending on the architecture of the device. To handle these CoreCon provides something called packages. Packages files are present in the datastore (e.g Microsoft.RemoteTools.Packages.xsl).

 

Let’s Look at a sample package(FileListPackage.xsl) which we can use for our FileList utility.

 

<?xml version="1.0" standalone="no"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

 

  <xsl:template match="/">

 

    <ADDONCONTAINER>

 

      <ADDON>

        <PACKAGECONTAINER>

          <PACKAGE ID="0695ABA4-6A85-484d-8C07-5E67FE44D6BC" NAME="FileList">

            <PACKAGETYPECONTAINER>

              <PACKAGETYPE Name="ARMV4" ID="ARMV4" Protected="true">

                <PROPERTYCONTAINER>

                  <PROPERTY ID="RemotePath" Protected="true">%CSIDL_PROGRAM_FILES%</PROPERTY>

                  <PROPERTY ID="RootPath" Protected="true">%CSIDL_PROGRAM_FILES%\MyUtility\ARMV4</PROPERTY>

                  <PROPERTY ID="CommandLine" Protected="true"/>

                  <PROPERTY ID="CPU" Protected="true">ARMV4</PROPERTY>

                </PROPERTYCONTAINER>

                <FILECONTAINER>

                  <FILE ID="FileList.exe"/>

                </FILECONTAINER>

              </PACKAGETYPE>

 

              <PACKAGETYPE Name="ARMV4I" ID="ARMV4I" Protected="true">

                <PROPERTYCONTAINER>

                  <PROPERTY ID="RemotePath" Protected="true">%CSIDL_PROGRAM_FILES%</PROPERTY>

                  <PROPERTY ID="RootPath" Protected="true">%CSIDL_PROGRAM_FILES%\MyUtility\ARMV4I</PROPERTY>

                  <PROPERTY ID="CommandLine" Protected="true"/>

                  <PROPERTY ID="CPU" Protected="true">ARMV4I</PROPERTY>

                </PROPERTYCONTAINER>

                <FILECONTAINER>

                  <FILE ID="FileList.exe"/>

                </FILECONTAINER>

              </PACKAGETYPE>

 

              <PACKAGETYPE Name="X86" ID="X86" Protected="true">

                <PROPERTYCONTAINER>

                  <PROPERTY ID="RemotePath" Protected="true">%CSIDL_PROGRAM_FILES%</PROPERTY>

                  <PROPERTY ID="RootPath" Protected="true">%CSIDL_PROGRAM_FILES%\MyUtility\X86</PROPERTY>

                  <PROPERTY ID="CommandLine" Protected="true"/>

                  <PROPERTY ID="CPU" Protected="true">X86</PROPERTY>

                </PROPERTYCONTAINER>

                <FILECONTAINER>

                  <FILE ID="FileList.exe"/>

                </FILECONTAINER>

              </PACKAGETYPE>

 

            </PACKAGETYPECONTAINER>

            <PROPERTYCONTAINER/>

          </PACKAGE>

        </PACKAGECONTAINER>

      </ADDON>

    </ADDONCONTAINER>

 

  </xsl:template>

 

</xsl:stylesheet>

 

Using Packages

Build the FileList.cpp for all the required Platforms and place the binaries under ‘Program Files\MyUtility\<Arch>’ (e.g Program Files \MyUtility\Armv4I\FileList.exe).

Let’s modify the utility to make use of the package. We need to do 2 things for that

-          Place the FileListPackage.xsl file in Global datastore directory (Documents and Settings\All users\Application Data\Microsoft\CoreCon\1.0\Addons).

-          Replace the FeilDeployer.sendfile  with FileDeployer.DownloadPackage

 

Replace the line

       fileDeployer.SendFile("FileList.exe", @"%CSIDL_PROGRAM_FILES%\FileList.exe");

With the below 2 lines

ObjectId packageObjID = new ObjectId("0695ABA4-6A85-484d-8C07-5E67FE44D6BC");

fileDeployer.DownloadPackage(packageObjID);

 

Now, we have made the FileList Utility architecture agnostic. Won’t it be good if there is way to know whether my utility has started properly in device. Won't it be good if I could interact with my utility, send/receive inputs and make it more interactive. Yes all are good and possible using CoreCon APIs. We will see how to write a device agent and build a FileViewer of our own.

Posted Wednesday, November 21, 2007 1:32 AM by MobileDevGroup | 2 Comments

Filed under:

CoreCon API – Part II

Let’s see some ways to do send/receive files to device and some process related functions. CoreCon provides a class called FileDeployer using which we can do file transfers across device and desktop. You should have established connection (Device.Connect()) to use the FileDeployer methods.

 

Device myDevice = GetPPC05Emulator();

myDevice.Connect();

FileDeployer fileDeployer = myDevice.GetFileDeployer();

fileDeployer.SendFile("foo.txt",@"%CSIDL_PROGRAM_FILES%\foo.txt");

 

This deploys the foo.txt (present in current directory) to “\Program files” folder in device. Note that you can use CSIDL paths in the both source and destination file names. CSIDL  values provide a unique system-independent way to identify special folders used frequently by applications, but which may not have the same name or location on any given system. Similarly there are APIs to do receive file and deploy bunch of files (using package) at a time. I will be discussing about the packages in detail in following blogs.

 

 RemoteProcess class gives us a way to start/stop process. Below code snippet starts a new process. Waits for some time (5 seconds), List all the process running and kills the started process.  

Device myDevice = GetPPC05Emulator();

myDevice.Connect();

 

//Start the calculator process in device

RemoteProcess remoteProc = myDevice.GetRemoteProcess();

bool bStarted = remoteProc.Start(@"%CSIDL_WINDOWS%\calc.exe", " ");

 

//List all running process

Collection<RemoteProcess> remoteProcCollection = myDevice.GetRunningProcesses();

int num = 0;

foreach (RemoteProcess rproc in remoteProcCollection)

{

num++;

      System.Console.WriteLine(num.ToString() + ". " + rproc.FileName);

}

//Kill the process

if (remoteProc.HasExited() == false)

{

remoteProc.Kill();

}

 

 

Let’s put all these together and write a small utility to do file listing in device. We will have a native app(FileList.exe) in device which will iterate the specified directory and print file names in a log. Our app will deploy this filelist.exe, run it with various parameters, get the log file and print in the console.

 

Create a Smartdevice console app targeting PPC 05. Copy paste the below code.

 

Source for FileList.cpp

/*

 * Gets the list of files/directories present int the path specified in cmd line argument.

 */

int _tmain(int argc, _TCHAR* argv[])

{

      int iRetVal = 0;

      if(argc <=1)

      {

            //No args passed

            return -1;

      }

      DeleteFile(L"\\foo.txt");

      HANDLE hLog = CreateFile(L"\\foo.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

      if(hLog == INVALID_HANDLE_VALUE)

      {

            //Error in creating log file

            return -1;

      }

 

      //Search the Directory

      TCHAR* szPath = new TCHAR[_tcslen(argv[1]) + 4];

      _tcscpy(szPath, argv[1]);

      _tcscat(szPath, L"\\*");

      WIN32_FIND_DATA findData;

      HANDLE hSearchFiles = INVALID_HANDLE_VALUE;

      hSearchFiles = FindFirstFile(szPath, &findData);

 

      if(hSearchFiles != INVALID_HANDLE_VALUE)

      {

            do

            {

                  TCHAR* szBuffer = new TCHAR[_tcslen(findData.cFileName) + 4];

                  _tcscpy(szBuffer, findData.cFileName );

                  _tcscat(szBuffer,L"\r\n");

                  DWORD numBytes;

                  WriteFile(hLog, szBuffer, _tcslen(szBuffer)*sizeof(TCHAR), &numBytes, NULL);

                  delete[] szBuffer;

            }while(FindNextFile(hSearchFiles, &findData)) ;

      }

      else

      {

            iRetVal = -1;

      }

      //Clean up

      if(szPath != NULL)

      {

            delete[] szPath;

            szPath = NULL;

      }

      if(hLog != INVALID_HANDLE_VALUE)

            CloseHandle(hLog);

 

      if(hSearchFiles != INVALID_HANDLE_VALUE)

            CloseHandle(hSearchFiles);

     

      return iRetVal;

}

 

Create a C# console application. Copy paste the below code in program.cs.

Place the FileList.exe in the same directory as output directory.

 

 

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.SmartDevice.Connectivity;

using System.Collections.ObjectModel;

 

namespace sample1

{

    class Program

    {

        static void Main(string[] args)

        {

            Device myDevice = GetPPC05Emulator();

 

            //Connect to the device.

            myDevice.Connect();

 

            FileDeployer fileDeployer = myDevice.GetFileDeployer();

            fileDeployer.SendFile("FileList.exe", @"%CSIDL_PROGRAM_FILES%\FileList.exe");

 

           

            //Start FileList process in device

            RemoteProcess remoteProc = myDevice.GetRemoteProcess();

            bool bStarted = remoteProc.Start(@"%CSIDL_PROGRAM_FILES%\FileList.exe", @"\Program files");

            if (bStarted == true)

            {

                while (remoteProc.HasExited() == false)

                {

                    System.Threading.Thread.Sleep(2000);

                }

            }

            int exitCode = remoteProc.GetExitCode();

            if (exitCode == 0)

            {

                fileDeployer.ReceiveFile(@"\foo.txt", "Filelist.txt");

            }

        }

 

        static Device GetPPC05Emulator()

        {

            DatastoreManager dsmgrObj = new DatastoreManager(1033);

 

            ObjectId ppc05PlatObjID = new ObjectId("4118C335-430C-497f-BE48-11C3316B135E");

            ObjectId PPC05EmuID = new ObjectId("25D984D9-0DFE-4DB1-A5A0-9A4F660BF2CE");

 

            Platform ppc05Plat = dsmgrObj.GetPlatform(ppc05PlatObjID);

            Device ppc05Emu = ppc05Plat.GetDevice(PPC05EmuID);

            return ppc05Emu;

        }

    }

}

 

 

Now, this utility could be used to do file listing of device.

 

--

Anand R

Posted Tuesday, November 20, 2007 6:09 AM by MobileDevGroup | 2 Comments

Filed under:

CoreCon API – Part 1

VSD is shipping Set of connectivity API which could be used to write remote tools (Remote file viewer etc) kind of Apps. This series of blog is aimed at giving an introduction about the connectivity APIs.

 

Datastore is a set of XML files on your desktop computer that contains information about the platforms, devices, emulators, and packages that are installed on the computer. The contents of the Datastore are modified whenever you install an SDK that is based on Windows CE such as Windows Mobile.  Let’s start with an app which looks at the datastore and enumerate list of SDKs and devices installed in the machine.

[Create a new C# Desktop console application. Add reference to Microsoft.Smartdevice.Connectivity.dll which can be found at <systemdrive>:\Program files\Common Files\Microsoft Shared\CoreCon\1.0\Bin ]

 

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.SmartDevice.Connectivity;

using System.Collections.ObjectModel;

 

namespace sample1

{

    class Program

    {

        static void Main(string[] args)

        {

            //Instead of 1033 use the locale ID of your app.

            DatastoreManager dsmgrObj = new DatastoreManager(1033);

 

            //Get all the platform entries present in Data store

            //Iterate through Collection of platforms

            Collection<Platform> platformCollection = dsmgrObj.GetPlatforms();

            foreach (Platform objplatform in platformCollection)

            {

                System.Console.WriteLine(objplatform.Name);

                Collection<Device> deviceCollection = objplatform.GetDevices();

                //List all the devices in the platform

                foreach (Device objdevice in deviceCollection)

                {

                    System.Console.WriteLine("\t" + objdevice.Name);

                }

            }

 

        }

    }

}

 

Let’s look at some options to connect to a device and get info regarding the device.

In the below sample I am connecting to PPC 05 emulator and getting info regarding virtual and physical memory. IDs of devices/SDK can be obtained from the datastore files which can be found in

<sysDrive>:\Documents and Settings\<username> \Local Settings\Application Data\Microsoft\CoreCon\1.0 (Non Vista OS) or <sysDrive>:\users\<username>\Application data\Microsoft\CoreCon\1.0 (Vista)

 

Open the conman_ds_platform.xsl file in visual studio. This file contains the information about all the installed SDKs.

 

DatastoreManager dsmgrObj = new DatastoreManager(1033);

 

ObjectId ppc05PlatObjID = new ObjectId("4118C335-430C-497f-BE48-11C3316B135E");

ObjectId PPC05EmuID = new ObjectId("25D984D9-0DFE-4DB1-A5A0-9A4F660BF2CE");

 

Platform ppc05Plat = dsmgrObj.GetPlatform(ppc05PlatObjID);

Device ppc05Emu = ppc05Plat.GetDevice(PPC05EmuID);

 

//Connect to the device.

ppc05Emu.Connect();

SystemInfo pp05EmuInfo = ppc05Emu.GetSystemInfo();

System.Console.WriteLine("Available Physical Memoory\t:\t"+pp05EmuInfo.AvailPhys);

System.Console.WriteLine("Total Physical Memoory    \t:\t" + pp05EmuInfo.TotalPhys);

System.Console.WriteLine("Available Virtual Memoory \t:\t" + pp05EmuInfo.AvailVirtual);

System.Console.WriteLine("Total Physical Memoory    \t:\t" + pp05EmuInfo.TotalVirtual);

System.Console.WriteLine(