|
.NET Remoting can be made to work in other languages, but it's a real b*tch. Since the messages are SOAP (assuming you use a SoapFormatter for the serialization sink), you can always tranform them.
There are many other options available, though. While you may not be comfortable with sockets, it's always good to learn new things! You could define a simple protocol using commands like SMTP, HTTP, and countless others. This would definitely be the most open approach.
Another way would be to host the ASP.NET runtime in your service (a little resource intensive, but not too bad) and host an XML Web Service. The SOAP bindings for these are industry standard, and Java and C++ (with, for example, the SOAP toolkit for C++ from Microsoft) should have no problems handling this.
It's really not that difficult hosting ASP.NET, either. ASP.NET Web Matrix (a free ASP.NET designer from Microsofties at http://www.asp.net[^]) does it, and VS.NET 2005 will do it for ASP.NET Web Application projects as well (so no more dependency on IIS! ). See the documentation for System.Web.Hosting.ApplicationHost in the .NET Framework SDK for more information. This would be just about as open as using a TCP protocol, except that it requires the client understand SOAP (and most languages do through extensions/mods, like Java, C++, Perl, etc.). IMO, it would even be a better approach since it allows you to develop a transport capable of more easily transporting complex objects, rather than having to serialize them to a byte[] array to send over a NetworkStream .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks for the input! I think I'll settle for sockets that send and receive XML formated commands. As the server sends the return as XML even now with remoting, I guess that should be the easiest. Hosting a Webservice is a bit of an overkill IMHO . Especially as the service should require as few resources as possible (.NET is such a resource killer anyway .
Thanks again!
Greets,
Daniel
---
SharpPrivacy - A free OpenPGP Implementation in c#
http://sharpprivacy.sf.net
|
|
|
|
|
hi,
I've two questions how do I mashal
BOOL WINAPI Toolhelp32ReadProcessMemory(
DWORD th32ProcessID,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD cbRead,
LPDWORD lpNumberOfBytesRead
);
using dll import so that I can use it with a buffer? I think I should use IntPtr, cut when I declare the buffer how should it be declared? need to use unsafe ? I'm trying to use it on a PocketPc, so MarshalAs class is not implemented ( as I've read), need I to make an array of bytes or what else?
thanks
Paolo
|
|
|
|
|
Yes, you do use an IntPtr , and no you don't need an unsafe context. I do a heck of a lot of P/Invoke (it's my forte', some might say) and have never once had to use an unsafe context.
To alloc the buffer (if you need to - in this case you don't since it's an output parameter), you can use several methods on the Marshal class in System.Runtime.InteropServices .
Since this is an output parameter, you can use Marshal.Copy(IntPtr, byte[], int, int) to copy the data to a byte[] array. The latter method is supported by the .NET CF.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
how can I use the Marshal.Copy if the buffer I need to write into is accessed by the funcion Toolhelp32ReadProcessMemory ? I declared a byte array as you told but I receive
D:\projects\PPC\.cs(28): Argument '3': cannot convert from 'byte[]' to 'System.IntPtr'
I did
<br />
byte[] databuffer= new byte[4096];<br />
uint byteread=0;<br />
Toolhelp32ReadProcessMemory(p.Handle,p.BaseAddress,databuffer,100,(uint)byteread);<br />
thanks again, you always answer me clearly and focusing the point!
Paolo
|
|
|
|
|
You can't just cast a byte[] to IntPtr . You have to allocate the memory to pass to Toolhelp32ReadProcessMemory . Since Marshal.AllocHGlobal isn't available on the .NET CF, you have to do it like so:
byte[] databuffer = new byte[100];
GCHandle handle = GCHandle.Alloc(databuffer);
IntPtr ptr = handle.AddrOfPinnedObject();
uint bytesread;
Toolhelp32ReadProcessMemory(p.Handle, b.BaseAddress, ptr, 100, bytesread);
handle.Free();
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I've done as you've told, but at this point
<br />
IntPtr ptr = handle.AddrOfPinnedObject();<br />
it's raised an ArgumentException, on MSDN it's written "An instance with nonprimitive (non-blittible) members cannot be pinned."
I think that it's due to the fact that .NET CF doesn't support byte[] as blittable element,any suggestion?
thanks again
Paolo
|
|
|
|
|
Yeah, I made a mistake there. You don't want to pin it because a byte is blittable, so just cast the GCHandle to an IntPtr :
IntPtr ptr = (IntPtr)handle; Sorry about that. I'm used to pinning non-blittable types.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I've fixed it but the function ToolHelp32ReadMemory fails, I don't know why but I'll check later, here's my source if anyone of you see an error, please tell me
<br />
[DllImport("toolhelp.dll")]<br />
private static extern bool Toolhelp32ReadProcessMemory( <br />
IntPtr th32ProcessID,<br />
int lpBaseAddress, <br />
IntPtr lpBuffer,<br />
uint cbRead, <br />
IntPtr lpNumberOfBytesRead <br />
);<br />
public static void DoDump(Process p)<br />
{<br />
<br />
try<br />
{<br />
byte[] databuffer = new byte[120];<br />
uint byteread=0;<br />
GCHandle br= GCHandle.Alloc(byteread);<br />
GCHandle handle = GCHandle.Alloc(databuffer);<br />
IntPtr ptr =(IntPtr)handle;<br />
<br />
if((Toolhelp32ReadProcessMemory(p.Handle,p.BaseAddess,(IntPtr)handle,120,(IntPtr)br)== false))<br />
I can't even see disassembly on PocketPC, but p.Handle and p.BaseAddress seems ok
thanks
Paolo
|
|
|
|
|
Don't use (IntPtr)br . You don't need to fix that in memory. Actually, you don't need to really fix anything at all, but the reason I gave you the code with the GCHandle was to get the address. What you need to pass to the P/Invoked function is an IntPtr, but now the address. Technically, the cbRead param should be an IntPtr too, passing it like so:
byte[] databuffer = new byte[120];
uint bytesread;
GCHandle handle = GCHandle.Alloc(databuffer);
bool ret = Toolhelp32ReadProcessMemory(p.Handle, p.BaseAddress,
(IntPtr)handle, (uint)databuffer.Length, bytesread);
handle.Free();
if (!ret) The method signature (for Windows CE - differs for Windows) should look like this:
[DllImport("toolhelp.dll")]
private static extern bool Toolhelp32ReadProcessMemory(
uint processID,
IntPtr baseAddress,
[Out] IntPtr buffer,
uint readbytes,
[Out] out uint bytesread); A DWORD is a 32-bit unsigned integer, which is uint C# (or UInt32 in .NET). LPVOID is an address, for which the bit width is dependent on the processor. An address on a 32-bit processor is 32 bits; on a 64-bit processor it's 64 bits. That's why you use an IntPtr . If you look at the API documentation for this function in Windows, you'd see SIZE_T . That, too, would be an IntPtr because it too is processor-dependent.
In your code, what's happening is that the data is getting read incorrectly because when it's marshaled all the params are pushed onto the stack. The callee will grab the params with their known sizes, meaning that your values are mis-aligned. It's very important that parameters map so a parameter of the same size, and the same is true for the return value (since it too is marshaled and pushed on the stack when the call returns).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
thanks again, but since Process class is defined as
<br />
private Process(IntPtr id, string procname, int threadcount, int baseaddress)<br />
{ <br />
handle = id;<br />
processName = procname;<br />
threadCount = threadcount;<br />
baseAddress = baseaddress;<br />
}<br />
as I've found here Creating a Microsoft .net .....Oricess Manager Application[^]
I've type mismatch, I tryed to convert int base address to IntPtr using GC.Alloc but it says it's not blittable, thanks again ( for christmas I'll sent you a gift or for your birthday )
Paolo
|
|
|
|
|
You should read the documentation for the IntPtr . First, you only need the GCHandle to get the address of the byte[] array. For any other numbers you need to pass where the param Type is an IntPtr (processor-dependent bit width), just use create a new IntPtr passing the number into the constructor, like:
IntPtr ptr = new IntPtr(p.Handle); If the Handle was 12345, then the IntPtr created with this as a param would be:
0x00003039
0x0000000000003039 This is not the address of the numeric variable, merely the number wrapped in a platform-dependent numeric type. The only place you need the address is for the byte[] array. Using the GCHandle is just the easiest way in the .NET CF to get it's address (the address of the first element which the rest of the elements allocated on the stack, which is why you pass the number of bytes in the array as the next param to Toolhelp32ReadProcessMemory .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I've done as you said,since I need a IntPtr for BaseAddress I did
<br />
IntPtr q = new IntPtr(p.BaseAddress);<br />
but for p.Handle that in ToolHelp32ProcessMemory is uint and I've a IntPtr how do I get the uint value?
have u got some good link to understand marshalling/pinvoke?
thanks
|
|
|
|
|
If you look at the documentation for IntPtr , it should be obvious:
uint id = (uint)p.Handle.ToInt32(); ...assuming p.Handle is declared as an IntPtr .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi,
i've built a UserControl which has a panel in it, I wish to be able to add
controls into it at design-time. I've tried to do it simple; just built
the control, compiled it into a DLL and add it to the ToolBox, then i've drag it to my WinForm. The control is visible and all its properties are working
great. but when i try to add a control into it (say a link labal), the control
does not get added! i see the outlines selections, with nothing inside (i.e. the text, color etc.) and when compiling and running the WinForm, the link does not appear. any idea?
thanks guys
|
|
|
|
|
Hi guys, it me again.
I've looked at MS KB 813450, and it didn't fix my problem.
which is realy weird... maybe i'm doing something wrong?
|
|
|
|
|
Hi guys,
I've identified the problem.
In my UserControl, i have a panel which is fill-docked on it.
when i remove it and try the KB 813450 solution, it works.
but i want to keep that panel. any idea?
thanks
|
|
|
|
|
hai there,
I think the above mentioned steps are that you following to build your application.
am i right ?. If yes it won't show any unexpected out put. The way that you are following is correct.
I think the problem is because of properties of controls that you are using here.
I tried this same thing and i never found any problem.
If you want code block that i tried.then please let me know.
hai, enjoy coding
Sreejith SS Nair
|
|
|
|
|
The Panel should be either protected or public (by default, the VS.NET designer makes these private). If it is not, it is not a separately designable container - it's just another part of your UserControl .
If you find that it does not work, you need to attribute your UserControl with a ParentControlDesigner derivative that allows controls to be added. You can find out more about this designer class in the .NET Framework SDK.
Both suggestion should work, however. I helped another guy with a similar problem about a month ago and the problem was resolved using one (or both) of these methods. You could always try searching the comments (see the "Search comments" link ago) for keywords like "ParentControlDesigner" for more information on that discussion.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks guys for the quick help.
the fixed the problem by removing the panel that was fill-docking my user control and adding the ParentControlDesigner attribute.
Now the controls are being added into the user control and not to one of its controls (i.e. the panel i wanted it to be added to).
thanks.
|
|
|
|
|
Hi,
I have a Windows Application for which I must create installation package. But this application also has a web reference to a web service.
During the installation, I must allow the user to enter the URL to the Web Service and based on that the Web Reference must be updated to the new URL. This problem is because the Web Service can be installed anywhere.
Any suggestion is welcome
Praveen Nayak
|
|
|
|
|
hi,
I would suggest you not to add a web reference in your windows proj. Instead create a proxy class for the web service you are using using "wsdl.exe" tool which can be run from .NET command prompt.
Now once the proxy class is created add it to your windows proj. and whereever you are calling the web service in your code change it and make an instance of this proxy class and call the web method.
If you open the proxy class you will find a line
"this.Url = "[the web service URL]";
externalise this by taking this web service path into your configuration file (app.exe.config) and use System.Configuration namespace to access the configuration file.
This way you can externalise the webservice call...
hope this helps you
regards,
Aryadip.
Cheers !! and have a Funky day !!
|
|
|
|
|
Hi Aryadip,
Thanks a lot man. The solution you have suggensted is simple and straightforward.
Truly a help.
Thanks,
Praveen
Think of it as evolution in action
|
|
|
|
|
You can add the URL to the Web Service to your .config file, for example. You can actually do this in the PropertyGrid of VS.NET under Bindings, (Advanced); or programmatically by setting the Url property of the Web Service proxy.
As far as changing that, you could extend the Installer class and in your derivative get the path to the .config file as well as the URL from the Context.Parameters property (Context is an inheritted property from the Installer class). You would have your Installer derivative use the XML DOM to change/add the URL to your .config file (perhaps in the appSettings section). You'd pass the two parameters by adding your assembly with the Installer class (attributed with the RunInstallerAttribute ) as a Custom Action, and modify the command-line with the switches you specified as the keys to get the parameter values from Context.Parameters . To get the path to your .config file, pass something like [INSTALLDIR]MyApp.exe.config. [INSTALLDIR] will be replaced by the installation directory and the trailing \. In decent Windows Installers development environments, you could actually specify the path to the file itself using a file key property, but VS.NET's project automatically generates these at compile time so you'd have to make such a change with a tool like Orca after it's compiled, which requires knowledge of the MSI database.
Another option - though I don't recommend it - may be easier. Just write the URL to the registry (a UI for registry entries is provided in the VS.NET Windows Installer project editor) and read it in your application. I don't recommend this since .NET applications really shouldn't use the registry. It makes touchless deployments impossible. In your case, however, this really doesn't seem to be a problem (though you should consider defaulting to some URL, like a public instance of this Web Service, if available).
So, how does the user put this URL in? In both cases, go to the UI editor and add a new form to the installation with a single text box. Give this text box a property name in the PropertyGrid. It's this property name (as [MYPROPNAME] - use the square backets) that you'd pass to your Installer derivative or write to the registry key. Again, you should consider a default (or make sure your app handles the absence of a URL correctly and in a user-friendly manner.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks Heath,
Aryadip helped with the first part and you with the second. The installation package is done.
Praveen
|
|
|
|
|