Solved

Change memory address value

Posted on 2011-03-09
23
514 Views
Last Modified: 2012-05-11
If I have memory address, how can I change its value?
0
Comment
Question by:Mohamed Abowarda
  • 10
  • 8
  • 2
  • +2
23 Comments
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35088477
Can you give some context to this question?  Why are you trying to change a value at a memory address?

As a general answer, in .Net you DON'T ever change a value at a specific memory address...unless we're talking about doing low level stuff in an "unsafe" block:
http://msdn.microsoft.com/en-us/library/chfa2zb8(VS.71).aspx
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 35088739
I have Console Application 1 that declare int variable, I used unsafe code to read the memory address for the int variable, I want to read or change this value on Console Application 2 using its memory address.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35088789
That sounds like a job better solved with .Net Remoting or WCF.

Does console1 spawn console2?  How big is the int value?  How often does the value need to be changed?  Can you simply make console2 return the value to console1 using an exitcode?  Does it only need to be one way communication?...or two way?

Give more details...
0
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
LVL 8

Expert Comment

by:Subrat (C++ windows/Linux)
ID: 35088838
In C/C++ you do as follows,

int a;
int* p = &a;
*p = 100;//Your desire value

Now a will hold value 100.
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 35088903
@Idle_Mind, I want to be able to read or change some variables in Console Application 1 using Console Application 2 anytime while the both processes is running.

The variable could be any data type not just integer.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35088917
...and this is .Net right?  Not pure C/C++?
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35088924
If .Net, what version you running?
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 35089036
.NET Framework 3.5
Visual Studio 2008
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35089653
*I have no idea how to do this using unsafe code*

I can show you how to communicate from console2 to console1 using REMOTING, though, if you like.  It is not a straight forward process...but passing things between processes never is.
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 35089891
@Idle_Mind: I tried to declare a pointer and set the pointer address to the other process variable memory address, I get the following exception:
"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

I would prefer if it's possible to change other processes variables in memory, however, if it's not possible you can show how to communicate between two processes without using sockets.
0
 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 450 total points
ID: 35089981
This low level stuff is definitely not my forte...

I believe you need to be using the WriteProcessMemory() API if you want to put your int value into a specific address:
http://msdn.microsoft.com/en-us/library/ms681674(VS.85).aspx
0
 
LVL 5

Assisted Solution

by:MedievalWarrior
MedievalWarrior earned 50 total points
ID: 35091109
You can't use the same memory pointer in one process  between different processes because the memory pointer doesn't exist in the other process. If you used .NET 4.0 then you could do this using managed code with the MemoryMappedFile Class.

MemoryMappedFile
http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspx

You would need to use P/Invoke though for 3.5

Creating Named Shared Memory
http://msdn.microsoft.com/en-us/library/aa366551(v=vs.85).aspx

The above is the closest you would get to work with a pointer that both processes could share but as Idle_Mind suggest there are other alternatives like remoting and named pipes
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 35093413
I don't think you can do what you describe.  Each application has it's own memory space and the adress you get is the adress of the memory in the assigned block of memory for the application, not a global memory adress.
You need some sort of interprocess communication - which I assume you do have already else how does app2 'know' the address to modify in app1 ?
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 35094521
@Idle_Mind: ReadProcessMemory() and WriteProcessMemory() works great! the only thing I need to know is how to get the process handle if I didn't started it by using System.Diagnostics.Process class?
0
 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 450 total points
ID: 35094727
You can use Process.GetProcessesByName()
// pass the app name with no path AND with no extension:
            Process[] ps = Process.GetProcessesByName("console");
            if (ps.Length > 0)
            {
                // do something with "ps[0].Handle"
            }

Open in new window


See:
http://msdn.microsoft.com/en-us/library/z3w4xdc9.aspx
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.handle.aspx

How are you going to initially pass the address from console1 to console2 though?...
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 35094909
Idle_Mind: I can use the registry to save the addresses and read it using the other application, if you have any other suggestion, please let me know.

I have increased the points to 500.

Thank you,
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35094929
If console1 spawns console2 then you could just pass it as a command line parameter.
0
 
LVL 5

Expert Comment

by:MedievalWarrior
ID: 35094934
It appears the OP has a static pointer to the variable in memory and doesn't actually *own the other process. If you do own the other console application it would be in your best interest to avoid using these methods since there are much safer alternatives.
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 35094967
@Idle_Mind: Console1 will not spawns Console2.

@MedievalWarrior: I actually own the both applications.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 35095874
You NEED some sort of interprocess communication for what you are doing.
Why not use that to just pass the value you want it changing to rather than attempting to modify the memory adress directly.
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 450 total points
ID: 35096619
Just so you have it, here's an example of using .Net remoting to send an int from Console2 to Console1.

Here's the remoteable object that allows the value to be passed between the processes.  Compile this as its own Class Library.  Both Console1 and Console2 will add a Reference to this DLL:
using System;
using System.Collections.Generic;
using System.Text;

namespace RemoteableObject
{
    public class Communicator : MarshalByRefObject 
    {

        public delegate void MyDelegate(int value);
        public event MyDelegate ValueSent;

        public void Send(int value)
        {
            if (ValueSent != null)
            {
                ValueSent(value);
            }
        }

        public override object InitializeLifetimeService()
        {
            return null; // object stays alive forever 
            // (otherwise it literally "dies" after 10 minutes when its lease expires)
        }

    }
}

Open in new window


Here is Console1 that will host the remoteable object and will receive the int value:
// Project --> Add Reference --> Browse Tab --> RemoteableObject.dll
// Project --> Add Reference --> .Net Tab --> System.Runtime.Remoting
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace ConsoleApplication1
{
    class Program
    {
        private static bool Shutdown = false;
        private static TcpChannel Channel = new TcpChannel(50001);
        private static RemoteableObject.Communicator Comms = new RemoteableObject.Communicator();

        static void Main(string[] args)
        {
            RemotingServices.Marshal(Comms, "Comms"); // the string value is a unique channel name identifier (it can be different than the variable)
            ChannelServices.RegisterChannel(Channel, false); // the remoteable object will be available on tcpchannel 50001
            Comms.ValueSent += new RemoteableObject.Communicator.MyDelegate(Comms_ValueSent);

            while (!Shutdown)
            {
                System.Threading.Thread.Sleep(100);
            }

            Console.Write("Press enter to continue...");
            Console.ReadLine();
        }

        static void Comms_ValueSent(int value)
        {
            Console.WriteLine("Value received: " + value.ToString());
            if (value == -1)
            {
                Shutdown = true;
            }
        }

    }
}

Open in new window


Finally, here is Console2 that will obtain a reference to the actual remoteable object being housed in Console1.  Note that we are connecting to localhost (because both apps are on the same computer) we are acccessing it "by name" on channel 50001.  You could actually use this to communicate across a LAN by replacing "localhost" with a computer name:
// Project --> Add Reference --> Browse Tab --> RemoteableObject.dll
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {

        static void Main(string[] args)
        {
            int value = 0;
            string entry;
            RemoteableObject.Communicator Comms = 
                (RemoteableObject.Communicator)Activator.GetObject(typeof(RemoteableObject.Communicator), "tcp://localhost:50001/Comms");
           
            do
            {
                Console.Write("Enter an integer to send (-1 to kill both apps): ");
                entry = Console.ReadLine();
                if (int.TryParse(entry, out value))
                {
                    try
                    {
                        Comms.Send(value);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Send failed: " + ex.ToString());
                        
                    }
                }
                else
                {
                    Console.WriteLine("Invalid Integer Entered.");
                }
            }
            while (value != -1);

            Console.Write("Press enter to continue...");
            Console.ReadLine();
        }

    }
}

Open in new window


Run Console1 first then load up Console2.  Enter an integer into Console2 and it should appear in Console1.  Enter -1 to shut down both apps.
0
 
LVL 12

Author Closing Comment

by:Mohamed Abowarda
ID: 35098986
Great!

Thanks a lot,
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35099105
You got that integrated into your project already?  =)
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

816 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now