Question

Getting a connected PocketPC's serial number/device ID from a desktop

Asked by: elorc

I'm trying to get the device ID and/or serial number from a connected Pocket PC using a desktop application I'm writing in VB.NET 2005. I've read through a lot of stuff that I found on Google... some useful, some not. What I understand is that apparently there's no way to directly request this information from the device. I found some code here that runs on the device: http://msdn.microsoft.com/en-us/library/ms172516(VS.80).aspx

That's fine and all, but it doesn't help me get the information back to the desktop application. The idea is that my desktop application uses OpenNETCF to retrieve files from a connected Pocket PC, but I only want it to do this with "authorized" devices. So the desktop app will grab the device's ID, check an authorization table, and if it's listed the app will pull the information it needs off the device.

I also tried the information I found at http://blog.opennetcf.com/ncowburn/2007/07/27/HOWTORetrieveTheDeviceIDFromTheDesktop.aspx, but I couldn't get this code to compile or work at all.

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2009-08-07 at 13:18:00ID24635965
Tags

RAPI

,

OpenNETCF

,

ActiveSync

,

Pocket PC

Topics

Visual Basic Programming

,

Windows MobileProgramming

,

Pocket PC Other

Participating Experts
1
Points
500
Comments
36

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. pocket pc and VB.NET
    Hello experts I am new to this VB.Net. Iam developing a small application for a pocket pc which is connected to a CF GPS unit. My question is how is it possible to read the data from the port using VB.NET.. In VB6 we have mscomm component...what is the equivivalent of it in ...
  2. Programming for PocketPC 2003
    Here's my situation: I'm a programmer, mostly Java/CF lately, but I am familiar enough with VB (ver. 6) enough to do what I needed too. I haven't used VB in a while though. I have an inventory database in MySQL, and I have an ipaq 2215, and a Socket SDIO plug in bar cod...
  3. PDA PocketPC Setfocus
    I am looking for assistance with an asp (not asp.net) page that will run on a Pocket PC 2003 ; with Pocket IE (or any other web browser). The problem I'm having is automatically setting the focus to the one text box on the asp page on page load/refresh. i've used Javascript...
  4. developing pocket pc application vb.net?
    Hello experts, I am trying to develop a pocket pc application using visual studio.net 2003 and what do I need to accomplish this? I tried putting a textbox and button on a form but I am unable to deploy it.

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: alexey_gusevPosted on 2009-08-07 at 13:24:32ID: 25046602

you can use the code from the last link, but instead of using KernelIoControl(), now from WM50 you can use GetDeviceID() API. This is not 100% the same as KernelIoControl() [which gives you true UUID of the device], but unique for your app.

so with client dll on PDA you can call it over RAPI with CeRapiInvoke() and get all required info.

 

by: elorcPosted on 2009-08-08 at 08:44:04ID: 25050574

I probably should have mentioned, this is an older Pocket PC. I don't know how upgradeable it is. I had to buy an upgrade CD from ebay to get it from PocketPC 2002 to 2003. HP doesn't provide upgrades for it anymore.

It's an iPaq H3950.

 

by: alexey_gusevPosted on 2009-08-08 at 08:52:18ID: 25050602

I believe KernelIoControl() worked also with PPC 2002 as well (don't remember as I used such devices a while ago :) )

But CeRapiInvoke() should work anyway. How have you compiled the code and what are the errors?

 

by: elorcPosted on 2009-08-10 at 10:21:18ID: 25061889

Well I guess I'm not sure where to begin with the second link. I guess the only way I can get RapiEx.dll is to compile it myself using the C code he provides, but I have no idea how to get it to compile. What kind of VS project do I need to create this as? Where do I put that section of code that he provides? I tried an MFC Smart Device DLL with no luck. I get two errors:

'IOCTL_HAL_GET_DEVICEID': undeclared identifier
'KernelIoControl': identifier not found

 

by: alexey_gusevPosted on 2009-08-10 at 10:37:26ID: 25062074

1) you need to create regular Win32 dll (under C++->Smart Device projects) that exports some symbols - namely the function you're going to call from the PC via CeRapiInvoke()

2) I assume you've got the OpenNETCF lib from here already: http://rapi.codeplex.com/

3) depending on which SDK version you're using, search in Include folder for IOCTL_HAL_GET_DEVICEID, eg in PocketPC SDK it is uniqueid.h

4) for KernelIoControl: http://msdn.microsoft.com/en-us/library/aa909165.aspx
and you get it as simple as that (assuming that coredll.dll is loaded - usually the case in 99%) - put it after all #include directives in your C/C++ dll code:

extern BOOL KernelIoControl(
  DWORD dwIoControlCode,
  LPVOID lpInBuf,
  DWORD nInBufSize,
  LPVOID lpOutBuf,
  DWORD nOutBufSize,
  LPDWORD lpBytesReturned
);

 

by: elorcPosted on 2009-08-10 at 10:53:37ID: 25062236

Ok cool, that seemed to compile without issue. So now, I would just put this DLL on the Pocket PC and from the desktop, I'd use the OpenNETCF's Invoke method?

 

by: alexey_gusevPosted on 2009-08-10 at 12:23:14ID: 25063137

yes. I'd advise to put the dll to \Windows on PDA and then yes, call it via Invoke on rapi object from desktop

 

by: alexey_gusevPosted on 2009-08-10 at 12:38:51ID: 25063297

and while we're on it, you probably need to do one additional thing to get it working:

(1) alter security policy on PDA: http://msdn.microsoft.com/en-us/library/bb416355.aspx

or

(2) sign the dll

it depends on the recent settings you have on your PDA, but usually WM6 has restricted RAPI by default

 

by: elorcPosted on 2009-08-12 at 07:15:34ID: 25078936

Okay, now it's time for me to sound like a total idiot... how do I access this provisioning XML file that contains the security policy? I don't know how to reference the existing one or apply any changes to it.

 

by: alexey_gusevPosted on 2009-08-12 at 07:28:15ID: 25079047

no worries, we're all ask questions :)

I suggest to do the following:

0. you said that your device is 2002, so such policies are not relevant there on iPaq H3950

1. in order to get some proof of concept and demonstrate that it works on recent devices (WM6 etc) you can use Remote tools (Registry Edit in particular) and change these values manually

2. alternatively, you can create Setup.dll and use registry API to do the same

3. in addition to #2, you can add xml file to your cab file so it is applied during the installation (see http://www.codeproject.com/KB/mobile/deploycertwithcode.aspx and similar). this sample is not 100% what you want, but it gives you the idea

 

by: elorcPosted on 2009-08-12 at 07:47:15ID: 25079278

I'm waiting for a Pocket PC 2003 upgrade for the iPaq to get here. Will that make it any easier to set up the security policies? I'm assuming it's something with the security on the device that's preventing my code from working. I put the RapiEx.dll file on the device in the Windows folder, and now I'm running code on the desktop (shown in the code section) to do the invoke. When it runs, the program crashes on the line where I do the actual invoke. The error is: "Value cannot be null. Parameter name: source"

Dim DeviceID As String = ""
 
Using cfRAPI As RAPI = New RAPI
    If Not cfRAPI.DevicePresent Then Exit Sub
 
    cfRAPI.Connect()
 
    If cfRAPI.Connected Then
        Dim outputBuffer() As Byte
        cfRAPI.Invoke("RapiEx", "CeGetDeviceID", New Byte() {}, outputBuffer)
 
        If outputBuffer Is Nothing Then
            sDeviceID = ""
        End If
 
        Dim PresetIDOffset As Int32 = BitConverter.ToInt32(outputBuffer, 4)
        Dim PlatformIDOffset As Int32 = BitConverter.ToInt32(outputBuffer, &HC)
        Dim PlatformIDSize As Int32 = BitConverter.ToInt32(outputBuffer, &H10)
 
        Dim sbID As New StringBuilder()
        sbID.Append([String].Format("{0:X8}-{1:X4}-{2:X4}-{3:X4}-", BitConverter.ToInt32(outputBuffer, PresetIDOffset), BitConverter.ToInt16(outputBuffer, PresetIDOffset + 4), BitConverter.ToInt16(outputBuffer, PresetIDOffset + 6), BitConverter.ToInt16(outputBuffer, PresetIDOffset + 8)))
 
        For i As Integer = PlatformIDOffset To PlatformIDOffset + (PlatformIDSize - 1)
            sbID.Append([String].Format("{0:X2}", outputBuffer(i)))
        Next i
 
        DeviceID = sbID.ToString()
    End If
End Using
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:

Select allOpen in new window

 

by: alexey_gusevPosted on 2009-08-12 at 08:14:01ID: 25079573

ok, can you include RAPI project to your solution and debug it to see where exactly it fails?
it should be either from desktop side (something with RAPI or parameters or marshalling) or on PDA.
put messageboxes to PDA dll to see whether it passes 100% or fails somewhere

 

by: elorcPosted on 2009-08-13 at 10:23:02ID: 25090714

This is the exception text that I'm getting. I put messageboxes in the RapiEx.dll code but none of them came up, so I'm assuming it didn't even make it that far.


System.ArgumentNullException was unhandled
  Message="Value cannot be null.
Parameter name: source"
  ParamName="source"
  Source="mscorlib"
  StackTrace:
       at System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object destination, Int32 startIndex, Int32 length)
       at System.Runtime.InteropServices.Marshal.Copy(IntPtr source, Byte[] destination, Int32 startIndex, Int32 length)
       at OpenNETCF.Desktop.Communication.RAPI.Invoke(String DLLPath, String FunctionName, Byte[] InputData, Byte[]& OutputData)
       at HandHeldSync.frmHandheldInfo.frmHandheldInfo_Load(Object sender, EventArgs e) in C:\Projects\HandHeldSync\HandHeldSync\SyncHandheld\frmHandheldInfo.vb:line 26
       at System.EventHandler.Invoke(Object sender, EventArgs e)
       at System.Windows.Forms.Form.OnLoad(EventArgs e)
       at System.Windows.Forms.Form.OnCreateControl()
       at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       at System.Windows.Forms.Control.CreateControl()
       at System.Windows.Forms.Control.WmShowWindow(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at System.Windows.Forms.ContainerControl.WndProc(Message& m)
       at System.Windows.Forms.Form.WmShowWindow(Message& m)
       at System.Windows.Forms.Form.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
       at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
       at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
       at System.Windows.Forms.Control.set_Visible(Boolean value)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at HandHeldSync.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()

 

by: alexey_gusevPosted on 2009-08-13 at 10:56:00ID: 25091034

looks like one of the parameters is wrong in Invoke call (presumably New Byte() {} - this should generate Null as you don't specify the size and any items in the byte array)

try to pass Nothing there

 

by: elorcPosted on 2009-08-13 at 11:34:01ID: 25091384

Ok, I changed the line to:

cfRAPI.Invoke("RapiEx", "CeGetDeviceID", Nothing, outputBuffer)

I get a slightly different error now... Null Reference Exception occurred in OpenNETCF.Desktop.Communication.dll:


System.NullReferenceException was unhandled
  Message="Object reference not set to an instance of an object."
  Source="OpenNETCF.Desktop.Communication"
  StackTrace:
       at OpenNETCF.Desktop.Communication.RAPI.Invoke(String DLLPath, String FunctionName, Byte[] InputData, Byte[]& OutputData)
       at HandHeldSync.frmHandheldInfo.frmHandheldInfo_Load(Object sender, EventArgs e) in C:\Projects\HandHeldSync\HandHeldSync\SyncHandheld\frmHandheldInfo.vb:line 26
       at System.EventHandler.Invoke(Object sender, EventArgs e)
       at System.Windows.Forms.Form.OnLoad(EventArgs e)
       at System.Windows.Forms.Form.OnCreateControl()
       at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       at System.Windows.Forms.Control.CreateControl()
       at System.Windows.Forms.Control.WmShowWindow(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at System.Windows.Forms.ContainerControl.WndProc(Message& m)
       at System.Windows.Forms.Form.WmShowWindow(Message& m)
       at System.Windows.Forms.Form.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
       at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
       at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
       at System.Windows.Forms.Control.set_Visible(Boolean value)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at HandHeldSync.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()

Dim DeviceID As String = ""
 
Using cfRAPI As RAPI = New RAPI
    If Not cfRAPI.DevicePresent Then Exit Sub
 
    cfRAPI.Connect()
 
    If cfRAPI.Connected Then
        Dim outputBuffer() As Byte
        cfRAPI.Invoke("RapiEx", "CeGetDeviceID", Nothing, outputBuffer)
 
        If outputBuffer Is Nothing Then
            sDeviceID = ""
        End If
 
        Dim PresetIDOffset As Int32 = BitConverter.ToInt32(outputBuffer, 4)
        Dim PlatformIDOffset As Int32 = BitConverter.ToInt32(outputBuffer, &HC)
        Dim PlatformIDSize As Int32 = BitConverter.ToInt32(outputBuffer, &H10)
 
        Dim sbID As New StringBuilder()
        sbID.Append([String].Format("{0:X8}-{1:X4}-{2:X4}-{3:X4}-", BitConverter.ToInt32(outputBuffer, PresetIDOffset), BitConverter.ToInt16(outputBuffer, PresetIDOffset + 4), BitConverter.ToInt16(outputBuffer, PresetIDOffset + 6), BitConverter.ToInt16(outputBuffer, PresetIDOffset + 8)))
 
        For i As Integer = PlatformIDOffset To PlatformIDOffset + (PlatformIDSize - 1)
            sbID.Append([String].Format("{0:X2}", outputBuffer(i)))
        Next i
 
        DeviceID = sbID.ToString()
    End If
End Using

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:

Select allOpen in new window

 

by: alexey_gusevPosted on 2009-08-13 at 11:50:22ID: 25091556

ok, that's how I used RAPI in one of the projects. it wasn't from OpenNETCF, but rather some home grown wrapper.

the bottom line is that the code in the snippet uses

<DllImport("rapi.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Public Shared Function CeRapiInvoke(ByVal dllPath As String, ByVal fnName As String, _
                                        ByVal cbInput As UInteger, ByVal pInput As IntPtr, _
                                        ByRef pcbOutput As UInteger, ByRef ppOutput As IntPtr, _
                                        ByVal res1 As Integer, ByVal res2 As Integer) As Integer
End Function

while OpenNETCF wrapper defines helper function as

public void Invoke(string DLLPath, string FunctionName, byte[] InputData, out byte[] OutputData)
{
}

and then uses InputData assuming it is NOT null.

P/Invoke declaration in OpenNETCF (converted from C# with http://www.developerfusion.com/tools/convert/csharp-to-vb/) is like that, ie practically the same as I used before:

<DllImport("rapi.dll", CharSet := CharSet.Unicode, SetLastError := True)> _
Friend Shared Function CeRapiInvoke(ByVal pDllPath As String, ByVal pFunctionName As String, ByVal cbInput As UInteger, ByVal pInput As IntPtr, ByRef pcbOutput As UInteger, ByRef ppOutput As IntPtr, _
ByVal ppIRAPIStream As IntPtr, ByVal dwReserved As UInteger) As Integer
End Function

Thus ensure that input buffer is not null and assigned some value, doesn't matter what, eg it can be 1 byte length with value = 0.

    Private Function IsDeviceSupported(ByRef errMsg As String) As Boolean
        Dim cbOutput As Integer
        Dim ppOutput As IntPtr
 
        Log("Checkig System Information...")
        Dim hr As Integer = Rapi.CeRapiInvoke("SetupDll.dll", "FnGetSystemInfo", 0, IntPtr.Zero, cbOutput, ppOutput, 0, 0)
        Dim logMsg As String = String.Format("hr = 0x{0:X}, LastError = 0x{1:X}, RapiLastError = 0x{2:X}", _
                    hr, Rapi.CeGetLastError(), Rapi.CeRapiGetError())
        Log(logMsg)
        If hr <> 0 Then
            If hr = NTE_BAD_SIGNATURE Then
                errMsg = "Unsupported device"
                Return False
            End If
            Dim errInfo As String = ""
            If cbOutput > 0 Then
                errInfo = Marshal.ReadInt32(ppOutput)
                Marshal.FreeCoTaskMem(ppOutput)
            Else
                errInfo = "No touchscreen driver is detected!"
            End If
            errMsg = "Unsupported device: " + errInfo
            Return False
        End If
        Return True
    End Function
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:

Select allOpen in new window

 

by: elorcPosted on 2009-08-13 at 12:45:59ID: 25092098

So instead of:

   cfRAPI.Invoke("RapiEx", "CeGetDeviceID", Nothing, outputBuffer)

I should use:

   cfRAPI.Invoke("RapiEx", "CeGetDeviceID", New Byte() {0}, outputBuffer)

?

 

by: alexey_gusevPosted on 2009-08-13 at 13:35:20ID: 25092619

yep

 

by: elorcPosted on 2009-08-14 at 06:23:15ID: 25097667

It's still not working, I'm getting an Argument Null Exception is mscorlib.dll. It's complaining about the "source" parameter like it was before. I don't understand why it keeps complaining about this.

System.ArgumentNullException was unhandled
  Message="Value cannot be null.
Parameter name: source"
  ParamName="source"
  Source="mscorlib"
  StackTrace:
       at System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object destination, Int32 startIndex, Int32 length)
       at System.Runtime.InteropServices.Marshal.Copy(IntPtr source, Byte[] destination, Int32 startIndex, Int32 length)
       at OpenNETCF.Desktop.Communication.RAPI.Invoke(String DLLPath, String FunctionName, Byte[] InputData, Byte[]& OutputData)
       at HandHeldSync.frmHandheldInfo.frmHandheldInfo_Load(Object sender, EventArgs e) in C:\Projects\HandHeldSync\HandHeldSync\SyncHandheld\frmHandheldInfo.vb:line 33
       at System.EventHandler.Invoke(Object sender, EventArgs e)
       at System.Windows.Forms.Form.OnLoad(EventArgs e)
       at System.Windows.Forms.Form.OnCreateControl()
       at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       at System.Windows.Forms.Control.CreateControl()
       at System.Windows.Forms.Control.WmShowWindow(Message& m)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       at System.Windows.Forms.ContainerControl.WndProc(Message& m)
       at System.Windows.Forms.Form.WmShowWindow(Message& m)
       at System.Windows.Forms.Form.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
       at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
       at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
       at System.Windows.Forms.Control.set_Visible(Boolean value)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(ApplicationContext context)
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
       at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
       at HandHeldSync.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()



I even created a completely new project that only attempts to get the device ID and it still is doing the same thing. I even created a C# project and used the same exact code from http://blog.opennetcf.com/ncowburn/2007/07/27/HOWTORetrieveTheDeviceIDFromTheDesktop.aspx (which didn't work). I changed the invoke line from "new byte[0] { }" to "new byte[] {0}"... I keep getting the same Argument Null Exception from mscorlib parameter "source"

 

by: alexey_gusevPosted on 2009-08-14 at 06:28:56ID: 25097727

ok, let's throw aside OpenNetCF for the moment, try attached wrapper.
it maybe less convenient but did the job for me :)

 

by: elorcPosted on 2009-08-14 at 06:37:37ID: 25097802

Looking at the OpenNETCF code behind the Invoke method, I see that it appears to be dying (around) here:

                  // copy the returned data from unmanaged to managed memory
                  Marshal.Copy(recvData, OutputData, 0, (int)recvSize);

recvData being the IntPtr that it's complaining about. So judging by the comment above the line and its location in the method's code, it looks like it's beyond the point where RapiEx.dll was invoked. A couple lines above it is:

                  // call the RAPI function
                  CeRapiInvoke(DLLPath, FunctionName, (uint)InputData.Length, sendData, out recvSize, out recvData, IntPtr.Zero, 0);

So does this mean that it's getting nothing back from CeGetDeviceID in my RapiEx.dll?

 

by: elorcPosted on 2009-08-14 at 06:38:23ID: 25097809

Ok, I'll try the wrapper you attached and I'll let you know what happens shortly. :)

 

by: elorcPosted on 2009-08-14 at 06:47:22ID: 25097891

Alright, that wrapper seems to work fine. The code below returns a number that I'd assume is the device ID. :)

I don't understand why OpenNETCF was being stupid, but since this wrapper seems to be doing exactly what I need/want it to do, I'll just use this instead.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 
        Dim i As Integer = Rapi.CeGetDeviceId()
        Label1.Text = i.ToString()
 
    End Sub
                                              
1:
2:
3:
4:
5:
6:

Select allOpen in new window

 

by: alexey_gusevPosted on 2009-08-14 at 06:52:01ID: 25097965

add messageboxes to RapiEx code to see it is indeed the same

 

by: elorcPosted on 2009-08-14 at 07:24:38ID: 25098361

Ok maybe I was wrong... Rapi.CeGetDeviceId returned a number at first, now it just returns -1. I have messageboxes in my RapiEx.dll but they never appeared.

The wrapper you provided me isn't supposed to reference RapiEx.dll, right?

 

by: elorcPosted on 2009-08-14 at 07:38:33ID: 25098514

I just tried it with another one of the PDAs I have and I get the same thing: The first time I click Button1, it returns a long number (I don't recall exactly what it returned but it was something like 184754553). Then if I click Button1 again, it returns -1.

Once it does that, even if I disconnect/reconnect the device, restart the program, it only returns -1 for that device.

Am I using the wrapper correctly?

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 
        Dim i As Integer = Rapi.CeGetDeviceId()
        Label1.Text = i.ToString()
 
    End Sub
                                              
1:
2:
3:
4:
5:
6:

Select allOpen in new window

 

by: elorcPosted on 2009-08-14 at 07:41:05ID: 25098541

Err, correction: Physically disconnecting the device and reconnecting it will stop the -1 thing from happening. I get a different number though (this time it's 2039296204), so it's safe to assume I'm not using the wrapper correctly.

Clicking Button1 once more  though does cause -1 to be returned until I physically disconnect the device from my computer and reconnect it again.

 

by: alexey_gusevPosted on 2009-08-14 at 08:13:29ID: 25098885

ah, I've overlooked it in your earlier post - CeGetDeviceId() is NOT that the RapiEx did :)
it just gets the ID of connected device from PC's point of view.

you still need to use CeRapiInvoke() and check what happens

 

by: elorcPosted on 2009-08-14 at 08:50:42ID: 25099394

I'm not having a lot of luck here but I suspect it's in part because I've never done anything like this before. I revised Button1 and its code is listed below.

When I run the application and click on the button, nothing crashes but nothing appears to be coming back from RapiEx.dll. outputInt and outputIntPtr are both 0, but i comes back as -2147014795. The messageboxes that I've put in RapiEx.dll do not come up on the device. I tried changing the first parameter on my invoke line from "RapiEx.dll" to "\Windows\RapiEx.dll" just to make sure that wasn't the issue, but I get back the same values for outputInt, outputIntPtr, and i (0, 0, -2147014795 respectively).

I also wasn't sure if it was a signing issue. I had signed RapiEx.dll with a certificate I created on my certificate server. So I tried putting a copy of RapiEx.dll that I had not signed on the PDA and once again got the same results described above.

What I did next is take a different PDA (same model) and connect it. This PDA doesn't even have RapiEx.dll loaded on it. I ran my program, clicked button1, and again got the same exact values (i was -2147014795 again).

In my code for CeGetDeviceId in RapiEx.dll, the very first line is a messagebox... so if it's hitting that function at all, shouldn't that messagebox be appearing on the PDA's screen? I think given the fact that I'm not seeing a messagebox, and I'm getting the same values returned even on a PDA that doesn't even have RapiEx.dll on it, RapiEx.dll isn't being called at all.

This is how CeGetDeviceID starts in my RapiEx.dll:

int CeGetDeviceID(DWORD cbInput, BYTE *pInput, DWORD *pcbOutput, BYTE **ppOutput, PVOID pVoid)
{
      MessageBox(NULL, L"CeGetDeviceID", L"Test", MB_OK);

...

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 
    Dim outputInt As Integer, outputIntPtr as IntPtr, i as Integer
 
    i = Rapi.CeRapiInvoke("RapiEx.dll", "CeGetDeviceID", 0, IntPtr.Zero, outputInt, outputIntPtr, 0, 0)
 
    MsgBox("i=" & i.ToString() & vbCrLf & "outputInt=" & outputInt.ToString() & vbCrLf & "outputIntPtr=" & outputIntPtr.ToString())
 
End Sub
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:

Select allOpen in new window

 

by: alexey_gusevPosted on 2009-08-14 at 08:57:23ID: 25099482

before we continue, I do hope you've called CeRapiInit()

 

by: elorcPosted on 2009-08-14 at 09:09:26ID: 25099661

Oops. I wasn't. I added the following line just above the invoke line:

Dim init As Integer = Rapi.CeRapiInit()

I'm getting similar behavior. The value for i is coming back slightly different (now it's -2147467259). outputInt, outputIntPtr, and init are all 0.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 
    Dim outputInt As Integer, outputIntPtr as IntPtr, i as Integer
 
    Dim init As Integer = rapi.CeRapiInit()
    i = Rapi.CeRapiInvoke("RapiEx.dll", "CeGetDeviceID", 0, IntPtr.Zero, outputInt, outputIntPtr, 0, 0)
 
    MsgBox("i=" & i.ToString() & vbCrLf & "outputInt=" & outputInt.ToString() & vbCrLf & "outputIntPtr=" & outputIntPtr.ToString() & vbCrLf & "init=" & init.ToString())
 
End Sub
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:

Select allOpen in new window

 

by: alexey_gusevPosted on 2009-08-14 at 09:16:37ID: 25099736

and init = 0 ?

it's a shame I don't have any 2002 device anymore, so we're mainly guessing now. And try OpenNETCF again, calling Connect() to initialise RAPI before you call Invoke()

 

by: elorcPosted on 2009-08-14 at 09:42:16ID: 25099983

Yes, init keeps returning 0. With OpenNETCF, I was already calling Connect().

The only other method I can think of is that I found a function specific to the iPAQ (which is what I'm using) that generates a file containing the device's asset information by running the asset export executable on the device.  I could read the serial number from there, but the problem is still getting the desktop to tell the device to do that.

 

by: alexey_gusevPosted on 2009-08-14 at 09:54:08ID: 25100088

you could use CeCreateProcess() to start the application on PDA.

can't think of anything else at the moment. I assume no firewall or antivirus run when you test your app?

 

by: elorcPosted on 2009-08-14 at 10:45:51ID: 25100472

Correct. No AV or firewall in the way.

I'll try the createprocess trick. That might be good enough to work for now until I can manage to get these devices updated to 2003.

 

by: elorcPosted on 2009-08-28 at 13:19:11ID: 31613109

It may not be the ideal solution in my opinion, but it's the only option I have. :)  This does the trick. Thanks for all of your help.

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...