|
-
Mar 3rd, 2003, 08:27 AM
#1
using a UDT in multiple applications
I have a DLL that has a UDT in it for employee
so it looks something like this
Public Type udtEmp
FirstName as string
LastName as string
EmpID as Long
End Type
etc...
anyways.. so i create the udt object in the first application.. and in the dll there is a public method to fill the udt with data using the userid which is passed to the method.. so i have a second exe that is called from the first one.. is there a way to get the variable info for the UDT in the second app from the first one.. like copying it from memory or something? right now i use command line params to pass the userID to child apps and run the dll's method again to fill a new UDT var in the child exe.. but i am trying to make my app more efficient.. what do you guys think?
-
Mar 3rd, 2003, 08:37 AM
#2
Retired VBF Adm1nistrator
Microsoft MVP : Visual Developer - Visual Basic [2004-2005]
-
Mar 3rd, 2003, 08:39 AM
#3
yeah just 1 udt... the udt itself has about 10 different string or long vars in it. .let me look at those links..
-
Mar 3rd, 2003, 08:53 AM
#4
hmm not sure if they will help me because they are dealing with arrays.. and woka is a nut
basically i dim the UDT in exe1.. fill the UDT in exe1 using the dlls GetEmpInfo method... and when i shell exe2.. i want to dim the UDT again in exe2 and use copymemory or something like that to fill the UDT in exe2 with the same data.. i could leave it how it is now and call the GetEmpInfo method in each app i suppose... i just thought this might be more efficent to have less hits to the database to get all the employee info
-
Mar 3rd, 2003, 09:06 AM
#5
Frenzied Member
First a quick rant about using classes rather than UDTs.
...mfnfng fng n dnmfn...
Right - if you must copy a UDT from one executable to another then you need to use the Readprocessmemory API call. I'd recommend you define the UDT in a .bas file and share it between the two exes for ease of use...then:
VB Code:
Public Type udtEmp
FirstName as String
LastName as String
EmpID as Long
End Type
Public Type udtEmp_Shadow
lpFirstName As Long
lpLastName As Long
EmpId As Long
End Type
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As ProcessAccessPriviledges, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Function LongFromOutOfprocessPointer(ByVal hProcess As Long, ByVal lpAddress As Long) As Long
Dim lRet As Long
Dim lBytesWritten As Long
Call ReadProcessMemory(hProcess, lpAddress, ByVal VarPtr(lRet), Len(lRet), lBytesWritten)
If lBytesWritten > 0 Then
LongFromOutOfprocessPointer = lRet
End If
End Function
Public Function IntegerFromOutOfprocessPointer(ByVal hProcess As Long, ByVal lpAddress As Long) As Integer
Dim lRet As Integer
Dim lBytesWritten As Long
Call ReadProcessMemory(hProcess, lpAddress, ByVal VarPtr(lRet), Len(lRet), lBytesWritten)
If lBytesWritten > 0 Then
IntegerFromOutOfprocessPointer = lRet
End If
End Function
Public Function StringFromOutOfProcessPointer(ByVal hProcess As Long, ByVal lpString As Long, ByVal Length As Long, ByVal Unicode As Boolean) As String
Dim buf() As Byte
Dim lRet As Long
Dim lBytesWritten As Long
Dim sTemp As String
ReDim buf(Length) As Byte
lRet = ReadProcessMemoryBytes(hProcess, lpString, buf(0), Length, lBytesWritten)
If lBytesWritten = 0 And Err.LastDllError = 0 Then
While lBytesWritten = 0 And Length > 0
Length = Length - 1
lRet = ReadProcessMemoryBytes(hProcess, lpString, buf(0), Length, lBytesWritten)
Wend
Else
If Err.LastDllError Then
Debug.Print LastSystemError
End If
End If
If lRet <> 0 Then
If Unicode Then
StringFromOutOfProcessPointer = StrConv(buf, vbFromUnicode)
Else
For lRet = 0 To lBytesWritten
If buf(lRet) = 0 Then
Exit For
End If
sTemp = sTemp & Chr$(buf(lRet))
Next lRet
StringFromOutOfProcessPointer = sTemp
End If
Else
If Err.LastDllError Then
Debug.Print LastSystemError
End If
End If
End Function
Then execuatble 1 sends executable 2 a registered windows message (as per the IPC using registered messages article) which tells it the address of the structure to be copied...this function must block until the second exe has read that structure or the memory address may be invalidated and your app(s) will fall over.
...more...
-
Mar 3rd, 2003, 09:13 AM
#6
Originally posted by MerrionComputin
First a quick rant about using classes rather than UDTs.
...mfnfng fng n dnmfn...
what is my benefit to creating a class for this?
-
Mar 3rd, 2003, 09:13 AM
#7
Frenzied Member
On receiving this message, exe 2 copies the _Shadow udt thus:
VB Code:
Dim tmpUDT As udtEmp
Dim tmpUDTShadow As udtEmp_Shadow
Dim lBytesWritten As Long, lRet As Long
Dim hProc As Long
hProc = OpenProcess(PROCESS_VM_READ,False,procid)
If hProc Then
lRet = ReadProcessMemory(hProc, lpUDT, VarPtr(tmpUDTShadow), Len(tmpUDTShadow), lBytesWritten)
If lBytesWritten = Len(tmpUDTShaow) Then
With tmpUDT
.FirstName = StringFromOutOfProcessPointer(hProc, tmpUDTShadow.lpFirstName, 1024)
.LastName = StringFromOutOfProcessPointer(hProc, tmpUDTShadow.lpLastName, 1024)
.EmpId = tmpUDTShadow.EmpId
End With
End If
End If
-
Mar 3rd, 2003, 09:15 AM
#8
Frenzied Member
what is my benefit to creating a class for this?
Public classes can be passed between ActiveX applications.
-
Mar 3rd, 2003, 09:17 AM
#9
Originally posted by MerrionComputin
Public classes can be passed between ActiveX applications.
but these are regular VB exes not activex exes.... the UDT and method for filling it are in an activex DLL
-
Mar 3rd, 2003, 09:23 AM
#10
Frenzied Member
Just can't stay out! Can I?
Duncan: Variable Length strings in the UDT? How will the "length" in the function get its value?
Both the apps need to have an uber-UDT to handle them, with the values in one element, and the lengths in another and pass them to the second app for restructuring.
"Brothers, you asked for it."
...Francisco Domingo Carlos Andres Sebastian D'Anconia
-
Mar 3rd, 2003, 09:28 AM
#11
Frenzied Member
Duncan: Variable Length strings in the UDT? How will the "length" in the function get its value?
Either assume a maximum or pass the length in as another member of the udt.
-
Mar 3rd, 2003, 10:12 AM
#12
Originally posted by kleinma
but these are regular VB exes not activex exes.... the UDT and method for filling it are in an activex DLL
Any reason for keeping it (App2) as a regular EXE and not an ActiveX EXE? I'm thinking that if you can change it to an ActiveX EXE, then you might be able to pass the UDT when calling your entrypoint....
Otherwise I think MC is right..... things will need to be copied through memory.
-
Mar 3rd, 2003, 10:59 AM
#13
Originally posted by techgnome
Any reason for keeping it (App2) as a regular EXE and not an ActiveX EXE? I'm thinking that if you can change it to an ActiveX EXE, then you might be able to pass the UDT when calling your entrypoint....
Otherwise I think MC is right..... things will need to be copied through memory.
yeah these apps get updated often and i dont want to have to register it each time as i would with an activex exe... so they are regular exes and they are accessed from a shared drive on the network.. so i dont have to reinstall them on each PC when there is an update
-
Mar 3rd, 2003, 11:01 AM
#14
Frenzied Member
If you are only working on windows NT and its derivatives you could create a named pipe and send the UDTs down it...
-
Mar 3rd, 2003, 11:07 AM
#15
sounds like i might be better off leaving it how it is... i mean it works now.. i was just looking for places to clean up code.. but this all sounds like it will be more work that the way it works now
-
Mar 28th, 2003, 11:29 AM
#16
Originally posted by kleinma
hmm not sure if they will help me because they are dealing with arrays.. and woka is a nut
If only you knew the truth 
OK, I am a tad confused by this whole out of process crap 
I have in one exe:
VB Code:
Dim udtData As typClient
udtData.hWnd = mlngHWND
udtData.AppName = "My Fishy Turtles"
lngServerhWnd = FindWindow(vbNullString, WINDOWTITLE_SERVER)
SendMessageLong lngServerhWnd, WMAttachClient, '??????????
and in my server I have:
VB Code:
Public Function VB_WindowProc(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim udtClient As typClient
If wMsg = WMAttachClient Then
'????????????
ElseIf wMsg = WMDetachClient Then
Else
VB_WindowProc = CallWindowProc(mlngOldProc, hwnd, wMsg, wParam, lParam)
End If
End Function
I can't work out the code you have posted. What would I need to add into the ????????'s to pass this UDT?
Woka
PS in the hProcess = hWnd ???
-
Mar 28th, 2003, 12:04 PM
#17
Frenzied Member
Worked example
If we take the following code and run it on my PC:
VB Code:
Option Explicit
Private Type ClientUDT
Name As String
Age As Long
IsHuman As Boolean
End Type
Private Sub Form_Load()
Dim clntThis As ClientUDT
With clntThis
.Name = "Duncan"
.Age = 32
.IsHuman = False
End With
Debug.Print VarPtr(clntThis)
Debug.Print VarPtr(clntThis.Name)
Debug.Print VarPtr(clntThis.Age)
Debug.Print VarPtr(clntThis.IsHuman)
End Sub
This returns:
1243700
1243700
1243704
1243708
Which shows that the structure clntThis is sited at address 1243700 and takes up 12 bytes.
However it is fairly obvious that you can't fit "Duncan" in 8 bytes ( especially at my current weight ) .
If we change the structure to have a fixed length string e.g.:
VB Code:
Private Type ClientUDT
Name As String * 20
Age As Long
IsHuman As Boolean
End Type
Then the results change to:
1243664
1243652
1243704
1243708
Which is 48 bytes and can fit "Duncan".
Therefore we can see that if the string in a UDT is fixed length it is stored in loine in the structure but if it is variable length it is stored elsewhere and a pointer to where it is stored is held in the structure.
If we go back to the variable length store dproic and run
VB Code:
Debug.Print VarPtr(clntThis.Name)
Debug.Print StrPtr(clntThis.Name)
This returns:
And if you peek the address 1243700 then you will see that it actually holds the value 1587500.
'...to be continued....
-
Mar 28th, 2003, 12:10 PM
#18
Frenzied Member
and if you peak the address at 1587496 (one 32 bit word less than StrPtr() returns) you get the value 6...which is the length of the string "Duncan" without the /0 terminator.
So from this you can see that so long as you know the format of the individual fields it is possible to recreate the structure from the address thus:-
VB Code:
Option Explicit
Private Type ClientUDT
Name As String
Age As Long
IsHuman As Boolean
End Type
'\\ API declarations...
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Long, Source As Long, ByVal Length As Long)
Private Declare Sub CopyMemoryByte Lib "kernel32" Alias "RtlMoveMemory" (Destination As Byte, Source As Long, ByVal Length As Long)
Private Declare Sub CopyMemoryFromByte Lib "kernel32" Alias "RtlMoveMemory" (Destination As Long, Source As Byte, ByVal Length As Long)
Public Function PeekByte(Address As Long) As Byte
Call CopyMemoryByte(PeekByte, ByVal Address, Len(PeekByte))
End Function
Public Function Peek(Address As Long) As Long
Call CopyMemory(Peek, ByVal Address, Len(Address))
End Function
Private Function UDTFromAddress(ByVal lpUDT As Long) As ClientUDT
Dim udtRet As ClientUDT
Dim sLen As Long
Dim lpString As Long
Dim btChars() As Byte
Dim lChar As Long
lpString = Peek(lpUDT)
sLen = Peek(lpString - 4)
With udtRet
.Age = Peek(lpUDT + 4)
.IsHuman = Peek(lpUDT + 8)
For lChar = 0 To sLen - 1
.Name = .Name & Chr$(PeekByte(lpString + (lChar * 2)))
Next lChar
End With
UDTFromAddress = udtRet
End Function
Private Sub Form_Load()
Dim clntThis As ClientUDT
Dim clntOut As ClientUDT
With clntThis
.Name = "Duncan"
.Age = 32
.IsHuman = False
End With
clntOut = UDTFromAddress(VarPtr(clntThis))
With clntOut
Debug.Print .Name
Debug.Print .Age
Debug.Print .IsHuman
End With
End Sub
However, as I noted earlier the address is local to the process. (With the weird street / house number analogy) so if we want to copy address 1587496 from another application, this code will actually look at that address in the current application and because that might not hold anything at all this will most likely crash the application.
Instead we need to use the API call ReadProcessmemory to get information from the other application's memory space.
'...to be continued..although less sensibly as I'm off to the pub now....
Last edited by MerrionComputin; Mar 28th, 2003 at 12:24 PM.
-
Mar 28th, 2003, 12:23 PM
#19
I wonder how many charact
Anyway, Merrion, when is your first book coming out?
Also, have any open positions in your firm?
-
Mar 28th, 2003, 12:32 PM
#20
Frenzied Member
Also, have any open positions in your firm?
We're effectively bankrupt so not the best time to be recruiting
-
Mar 29th, 2003, 06:57 AM
#21
'...to be continued..although less sensibly as I'm off to the pub now....
Arrrrrrrr....! Noooooooo...where's the code on reading memory from another app? You can't stop there....
Good tutorial 
Cheers.
Woka
-
Mar 29th, 2003, 07:04 AM
#22
Frenzied Member
I'm back now...and the full Irish breakfast is working it's magic so the rest of the code will be along presently...
-
Mar 29th, 2003, 07:06 AM
#23
Retired VBF Adm1nistrator
Duncan, you really should write a book ya know.
I've ****all money to spare, but I'd buy it!
Microsoft MVP : Visual Developer - Visual Basic [2004-2005]
-
Mar 29th, 2003, 07:38 AM
#24
Frenzied Member
Part 2 - Reading another process' memory
If you run several copies of this above program you will notice that they all seem to use the samem meory addresses. It is quite obvious that the two programs aren't actually running in the same area of memory or they would trample all over each other so there must be some other explanation.
As it turns out the address returned by VarPtr and used in CopyMemory is not an absolute address but rather it is expressed relative to the base address of the process. What this means is that if I load two programs, one might load at the address 160000 and the next instance load at 240000. If I query and address in the one process and it says it is 100 this means 16000 + 100 - and similarily the same address in the second process would mean 240000 + 100.
(warning: this is an over simplification as in reality there's a whole load of funky paging stuff going on but it serves to illustrate the prinicple).
Therefore if you know the base address of a process you can add the relative address and get the true address of another process' memory. This is how a debugger works, for instance.
As it happens Win32 includes a number of functions originally written to allow people to design debuggers which allow you to access another process' memory - ReadProcessmemory being the most important.
'...goes for more coffee....
-
Mar 29th, 2003, 08:12 AM
#25
Frenzied Member
The VB declaration of ReadProcessmemory is:
VB Code:
Declare Function ReadProcessMemoryLong Lib "kernel32" _
Alias "ReadProcessMemory" (ByVal hProcess As Long, _
ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, _
ByVal nSize As Long, _
lpNumberOfBytesWritten As Long) As Long
Where
hProcess is a handle to the other application which has been opened with PROCESS_VM_READ access,
lpBaseAddress is the address to read from as it is known to the other application,
lpBuffer is apointer to an area in this application's memory to copy the result to
nSize is the number of bytes you want to copy and
lpNumberOfBytesWritten returns the number of bytes that were successfully copied.
You absolutely must supply a variable for this call to put the lpNumberOfBytesWritten into or your app will bomb out spectacularily.
-
Mar 29th, 2003, 08:28 AM
#26
Frenzied Member
For the sake of simplicity this call can be wrapped up in two utility functions - one of which returns a Long value from a pointer in another process' memory and another wich returns a string from a pointer in another application's memory thus:-
VB Code:
Private Declare Function ReadProcessMemoryBytes Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, lpBuffer As Byte, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Function LongFromOutOfprocessPointer(ByVal hProcess As Long, ByVal lpAddress As Long) As Long
Dim lRet As Long
Dim lBytesWritten As Long
Call ReadProcessMemory(hProcess, lpAddress, ByVal VarPtr(lRet), Len(lRet), lBytesWritten)
If lBytesWritten > 0 Then
LongFromOutOfprocessPointer = lRet
End If
End Function
Public Function StringFromOutOfProcessPointer(ByVal hProcess As Long, ByVal lpString As Long, ByVal Length As Long, ByVal Unicode As Boolean) As String
Dim buf() As Byte
Dim lRet As Long
Dim lBytesWritten As Long
Dim sTemp As String
ReDim buf(Length) As Byte
lRet = ReadProcessMemoryBytes(hProcess, lpString, buf(0), Length, lBytesWritten)
If lBytesWritten = 0 And Err.LastDllError = 0 Then
While lBytesWritten = 0 And Length > 0
Length = Length - 1
lRet = ReadProcessMemoryBytes(hProcess, lpString, buf(0), Length, lBytesWritten)
Wend
Else
If Err.LastDllError Then
Debug.Print LastSystemError
End If
End If
If lRet <> 0 Then
If Unicode Then
StringFromOutOfProcessPointer = StrConv(buf, vbFromUnicode)
Else
For lRet = 0 To lBytesWritten
If buf(lRet) = 0 Then
Exit For
End If
sTemp = sTemp & Chr$(buf(lRet))
Next lRet
StringFromOutOfProcessPointer = sTemp
End If
Else
If Err.LastDllError Then
Debug.Print LastSystemError
End If
End If
In the second one I have added som error trapping which I recommend using after any API call. The code for LastSystemError is:
VB Code:
Private Declare Function FormatMessage Lib "kernel32" _
Alias "FormatMessageA" (ByVal dwFlags As Long, _
ByVal lpSource As Long, _
ByVal dwMessageId As Long, _
ByVal dwLanguageId As Long, _
ByVal lpBuffer As String, _
ByVal nSize As Long, _
Arguments As Long) As Long
'\\ -- [ LastSystemError ]----------------------------------
'\\ Returns the message from the system which describes the
'\\ last dll error to occur, as
'\\ held in Err.LastDllError. This function should be
'\\ called as soon after the API call
'\\ which might have errored, as this member can be reset
'\\ to zero by subsequent API calls.
'\\ --------------------------------------------------------
Public Function LastSystemError() As String
Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Dim sError As String * 500 '\\ Preinitilise a string buffer to put any error message into
Dim lErrNum As Long
Dim lErrMsg As Long
lErrNum = Err.LastDllError
lErrMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, lErrNum, 0, sError, Len(sError), 0)
LastSystemError = Trim(sError)
End Function
-
Mar 29th, 2003, 09:03 AM
#27
Frenzied Member
Getting the process Id
In order to open the other process to read it's memory you need to know the process id. You can get this if you have the window handle of the window that sent you the message thus:-
VB Code:
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpProcId As Long) As Long
Public Function ProcessIdFromHwnd(ByVal hwnd As Long) As Long
Dim lProc As Long
If GetWindowThreadProcessId(hwnd, lProc) Then
ProcessIdFromHwnd = lProc
End If
End Function
And you pass this in to OpenProcess in order to get the hProc parameter to pass to LongFromOutOfprocessPointer and StringFromOutOfprocessPointer...
VB Code:
Public Enum ProcessAccessPriviledges
PROCESS_TERMINATE = &H1
PROCESS_CREATE_THREAD = &H2
PROCESS_SET_SESSIONID = &H4
PROCESS_VM_OPERATION = &H8
PROCESS_VM_READ = &H10
PROCESS_VM_WRITE = &H20
PROCESS_DUP_HANDLE = &H40
PROCESS_CREATE_PROCESS = &H80
PROCESS_SET_QUOTA = &H100
PROCESS_SET_INFORMATION = &H200
PROCESS_QUERY_INFORMATION = &H400
PROCESS_SYNCHRONISE = &H100000
PROCESS_ALL_ACCESS = &H100FFF
End Enum
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As ProcessAccessPriviledges, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
-
Mar 29th, 2003, 09:20 AM
#28
Frenzied Member
So if your sending app fills out the UDT and then passes it accross thus:
VB Code:
Private Type ClientUDT
Name As String
Age As Long
IsHuman As Boolean
End Type
Dim lTargetWnd As Long 'window to send the message to in the recieving app - use FindWindow to populate this?
'...
Dim myUdt As ClientUDT
With myUdt
.Name = Duncan
.Age = 31
.IsHuman = False
End With
Call SendMessage(lTargetWnd, MSG_UDT_FULL, lSourceWnd, VarPtr(myUdt))
Then your target application can process this message and read the UDT from the sender's address thus:
VB Code:
'..in WNDPROC
If msg = MSG_UDT_FULL Then
Dim myUDT As ClientUDT
myUDT = UDTFromOtherprocessAddress(wParam, lParam)
End If
Where
VB Code:
Private Function UDTFromOtherprocessAddress(ByVal hwndOther As Long, ByVal lpUDT As Long) As ClientUDT
Dim udtRet As ClientUDT
Dim hProc As Long
Dim sLen As Long
Dim lpString As Long
Dim lChar As Long
hProc = OpenProcess(PROCESS_VM_READ , ProcessIdFromHwnd(hwndOther ))
If hProc Then
lpString = LongFromOutOfprocessPointer(hProc, lpUDT)
sLen = LongFromOutOfprocessPointer(hproc, lpString - 4)
With udtRet
.Age = LongFromOutOfprocessPointer(hProc, lpUDT + 4)
.IsHuman = LongFromOutOfprocessPointer(hProc, lpUDT + 8)
.Name = StringFromOutOfProcessPointer(hProc, lpString, sLen, True)
End With
End If
UDTFromAddress = udtRet
End Function
'...The End...or is it?.....
-
Mar 29th, 2003, 11:31 AM
#29
PowerPoster
Have you ever considered using Memory Mapped Files??
-
Mar 29th, 2003, 07:06 PM
#30
Frenzied Member
Have you ever considered using Memory Mapped Files??
There are many ways to do this - that was just one of them...
-
Mar 30th, 2003, 11:23 AM
#31
What others ways are there?
What's a Memory Mapped File?
I have a bad hangover today, got hacked to death at Sunday League footy, and have so far got no work done 
Hungry Woka
Last edited by Wokawidget; Mar 30th, 2003 at 11:30 AM.
-
Mar 30th, 2003, 12:01 PM
#32
OK, I understand how the code you posted works, and I grasp the concept of the same memory address, but different if the base memory is brought into account.
I am dealing with byte arrays, which represent the contents of property Bags. I can get the memory address for the start of the byte array, and I can pass that and the owning hWnd, but how do I deal with the length or the byte array?
Woka
-
Mar 30th, 2003, 12:03 PM
#33
Dunc, by the way, this is much appreciated 
kaWo
-
Mar 31st, 2003, 04:00 AM
#34
Frenzied Member
There is aslo a way of sending data between applications using the WM_COPY message.
-
Apr 1st, 2003, 05:58 AM
#35
It's sunny yet disturbingly windy...Does not make sense!
Now, if I wanted to pass a byte array, would I use the following:
VB Code:
Public Type mtypDataStruct
Pointer As Long
Length As Long
End Type
Now say I have a byte array:
From this byte array I can find the starting memory address:
VB Code:
Dim udtDS As mtypDataStruct
Pointer = VarPtr(Fish(0))
and it's length:
VB Code:
Length = UBound(Fish) + 1
Now since the data structure UDT is a constant fixed length I can literally pass ONLY the start address of this using SendMessage, oh and along with the hWnd where it is located.
From this when when the message is received, in the WinProc function, I can get the pointer and length for the data struct, from the other process memory, which in turn will let me reconstruct my byte array...
Is this the correct way to pass I byte array between applications, using Mirrions tutorial?
woKa
-
Apr 1st, 2003, 08:01 AM
#36
Frenzied Member
Is this the correct way to pass I byte array between applications, using Mirrions tutorial?
Who Mirrion?
Yes - if your UDT is fixed length that should work fine.
-
Apr 1st, 2003, 09:11 AM
#37
Mirrion, Merrion, Mellon, Turnip Soup...
'tis all the same 
You have to work in a 3 demsional, fuzzy vortex, logic cube...then things become way clearer 
Woka
-
Apr 1st, 2003, 05:21 PM
#38
PowerPoster
Duncan:
Late responding -- been out of pocket.
Wasn't trying to rain on your parade with my input re Memory Mapped Files, just thought Kleinma might not know about them and might be a better way in his app than passing structures (UDT).
If I haven't thanked you before, let me thank your now for all your input to the forum. I for one always enjoy reading your comments and have learned a lot from your posts.
David
-
Apr 1st, 2003, 06:06 PM
#39
Addicted Member
Some great code goin' about here but can I interject something a little more simpler? (subscriber to the KISS principle).
If you have a UDT defined in two different apps and you want to pass the data from one instance of a UDT in one app to another instance of the same UDT (in structure) in another app, and the UDT's structure doesn't contain variable length strings, then you could pass the data as a buffered string.
Now this is not the BEST way, but it is rather simple.
Let me explain.
In each app:
Public Type udtEmp
FirstName As String * 50
LastName As String * 50
EmpID As Long
End Type
Public Type udtEmpBuffer
Data As String * 104 '50 + 50 + 4
End Type
When you want to buffer the data in one app:
Dim uEmp As udtEmp
Dim uBuffer As udtEmpBuffer
With uEmp
.FirstName = "John"
.LastName = "Doe" ' I know, very creative
.EmpID = 1001
End With
LSet uBuffer = uEmp
And then pass the data as a string ie:
objApp2.HereIsSomeData(uBuffer.Data)
And on the receiving side do the reverse.
Dim uEmp as udtEmp
Dim uBuffer as udtEmpBuffer
uEmpBuffer.Data = sPassedString
LSet udtEmp = uEmpBuffer
It's quick and comes with a built in parser. The only major drawbacks are 1) if you don't use fixed-length data, then you need to define the size of the Data element of the Buffer UDT to some huge size, and 2) If the UDT's structure needs to be changed, then you need to change it in two places.
-
Apr 1st, 2003, 07:19 PM
#40
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|