Jump to content

Shared Memory C# StructLayout


sirbow2

Recommended Posts

There's no struct involved at all, since AIDA64 publishes sensor readings in shared memory as a single long string (set of characters), using XML format. You can simply read the full shared memory into a character variable, and display it or post-process it.

Regards,

Fiery

Link to comment
Share on other sites

There's no struct involved at all, since AIDA64 publishes sensor readings in shared memory as a single long string (set of characters), using XML format. You can simply read the full shared memory into a character variable, and display it or post-process it.

Regards,

Fiery

thanks for the info, ive managed to get the speed fan code up and running. so now all i need to do is change the shared memory address in the C# program, remove the speedfan structLayout, how would i interpret this data into simple integers? XMLReader?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;

namespace SpeedFanReader
{
   class SpeedFan
   {

       static void printHeader(SpeedFan.Data d)
       {
           String header = "";
           for (int i = 0; i < d.numFans; i++)
           {
               header += "Fan " + i + ",";
           }
           for (int i = 0; i < d.numTemps; i++)
           {
               header += "Temp " + i + ",";
           }
           for (int i = 0; i < d.numVolts; i++)
           {
               header += "Volt " + i + ",";
           }
           header += "Flags";
           Console.WriteLine(header);
       }

       static void printData(SpeedFan.Data d)
       {
           if (d != null)
           {
               String output = "";
               for (int i = 0; i < d.numFans; i++)
               {
                   output += d.fans[i] + ",";
               }
               for (int i = 0; i < d.numTemps; i++)
               {
                   output += d.temps[i] + ",";
               }
               for (int i = 0; i < d.numVolts; i++)
               {
                   output += d.volts[i] + ",";
               }
               output += d.flags;

               Console.WriteLine(output);
           }
       }

       static void Main(string[] args)
       {
           SpeedFan sf = new SpeedFan();

           sf.OpenView();
           bool done = false;
           StreamWriter writer = null;
           if (args.Length > 0)
           {
               try
               {
                   writer = new StreamWriter(args[0]);
                   writer.AutoFlush = true;
                   Console.SetOut(writer); // redirect stdout to the file
               }
               catch (IOException e)
               {
                   Console.WriteLine("Failed to open file: " + args[0] + " : " + e.Message);
                   return;
               }
           }
           try
           {
               bool first = true;
               while (!done)
               {
                   SpeedFan.Data d = sf.GetData();

                   if (first)
                   {
                       printHeader(d);
                       first = false;
                   }
                   printData(d);

                   if (writer != null)
                       writer.Flush();

                   // Sleep for a second
                   System.Threading.Thread.Sleep(1000);
               }
           }
           finally
           {
               if (writer != null)
               {
                   Console.SetOut(new StreamWriter(Console.OpenStandardOutput()));
                   writer.Flush();
                   writer.Close();
               }
               Console.WriteLine("Done!");
           }
       }

       [structLayout(LayoutKind.Sequential, Pack = 1)]
       public class Data
       {
           public ushort version;
           public ushort flags;
           public Int32 size;
           public Int32 handle;
           public ushort numTemps;
           public ushort numFans;
           public ushort numVolts;
           [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
           public Int32[] temps;
           [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
           public Int32[] fans;
           [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
           public Int32[] volts;

           public Data()
           {
               temps = new Int32[32];
               fans = new Int32[32];
               volts = new Int32[32];
           }
       }

       #region Win32 API stuff
       public const int FILE_MAP_READ = 0x0004;

       [DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
       internal static extern IntPtr OpenFileMapping(int dwDesiredAccess,
           bool bInheritHandle, StringBuilder lpName);

       [DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
       internal static extern IntPtr MapViewOfFile(IntPtr hFileMapping,
           int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow,
           int dwNumberOfBytesToMap);

       [DllImport("Kernel32.dll")]
       internal static extern bool UnmapViewOfFile(IntPtr map);

       [DllImport("kernel32.dll")]
       internal static extern bool CloseHandle(IntPtr hObject);
       #endregion

       private bool fileOpen = false;
       private IntPtr map;
       private IntPtr handle;

       ~SpeedFan()
       {
           CloseView();
       }

       public bool OpenView()
       {
           if (!fileOpen)
           {
               StringBuilder sharedMemFile = new StringBuilder("SpeedFan64_SensorValues");
               handle = OpenFileMapping(FILE_MAP_READ, false, sharedMemFile);
               if (handle == IntPtr.Zero)
               {
                   throw new Exception("Unable to open file mapping.");
               }
               map = MapViewOfFile(handle, FILE_MAP_READ, 0, 0, Marshal.SizeOf((Type)typeof(Data)));
               if (map == IntPtr.Zero)
               {
                   throw new Exception("Unable to read shared memory.");
               }
               fileOpen = true;
           }
           return fileOpen;
       }

       public void CloseView()
       {
           if (fileOpen)
           {
               UnmapViewOfFile(map);
               CloseHandle(handle);
           }
       }

       public Data GetData()
       {
           if (fileOpen)
           {
               Data data = (Data)Marshal.PtrToStructure(map, typeof(Data));

               return data;
           }
           else
               return null;
       }
   }
}

Link to comment
Share on other sites

Either you implement a XML parser, or simply process the long string, to convert it to a format that you need. It's not a real, complex XML string, just a dumb XML-like format B)

could you help me with that code? no one else seems to understand what im trying to do, either method i dont care, i jsut need the values as int and floats etc.

Link to comment
Share on other sites

could you help me with that code? no one else seems to understand what im trying to do, either method i dont care, i jsut need the values as int and floats etc.

well i managed to get some code to work that gets the memory and writes to a file, but that file is all little "ㄱ⼼慶畬㹥⼼祳㹳猼ç¹ã°¾æ‘©åŒ¾ä¥”ä•â¼¼æ‘©"s.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;

namespace SharedMemSaveToFile
{
   class SharedMemSaver
   {
       public class Data
       {
           static void Main(string[] args)
           {
               SharedMemSaver sf = new SharedMemSaver();
               sf.OpenView();
               String d = sf.GetData();
               System.IO.StreamWriter file = new System.IO.StreamWriter("C:\\files.txt");
               file.WriteLine(d);
           }
       }

       #region Win32 API stuff
       public const int FILE_MAP_READ = 0x0004;

       [DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
       internal static extern IntPtr OpenFileMapping(int dwDesiredAccess,
           bool bInheritHandle, StringBuilder lpName);

       [DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
       internal static extern IntPtr MapViewOfFile(IntPtr hFileMapping,
           int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow,
           int dwNumberOfBytesToMap);

       [DllImport("Kernel32.dll")]
       internal static extern bool UnmapViewOfFile(IntPtr map);

       [DllImport("kernel32.dll")]
       internal static extern bool CloseHandle(IntPtr hObject);
       #endregion

       private bool fileOpen = false;
       private IntPtr map;
       private IntPtr handle;

       ~SharedMemSaver()
       {
           CloseView();
       }

       public bool OpenView()
       {
           if (!fileOpen)
           {
               StringBuilder sharedMemFile = new StringBuilder("AIDA64_SensorValues");
               handle = OpenFileMapping(FILE_MAP_READ, false, sharedMemFile);
               if (handle == IntPtr.Zero)
               {
                   throw new Exception("Unable to open file mapping.");
               }
               map = MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0);
               if (map == IntPtr.Zero)
               {
                   throw new Exception("Unable to read shared memory.");
               }
               fileOpen = true;
           }
           return fileOpen;
       }

       public void CloseView()
       {
           if (fileOpen)
           {
               UnmapViewOfFile(map);
               CloseHandle(handle);
           }
       }

       public String GetData()
       {
           if (fileOpen)
           {
               String data = (String)Marshal.PtrToStringAuto(map);
               return data;
           }
           else
           {
               return null;
           }
       }
   }
}

Link to comment
Share on other sites

ahh well i got it to work, i set the length to 300 for ex then the CPU mulitplier would change to 11 from 6 thus adding a character and messing up the length. so since i was never going to use all the data given by aida i just selected a few options for shared memory that dont change in length.

Link to comment
Share on other sites

Please note that the shared memory content doesn't have a fixed length, so the number of characters is dynamically changed depending on the shared memory content. We indicate the end of string by the NUL character. If you use a char* or PChar sort of variable, then it should be easy to handle a zero-terminated string.

Link to comment
Share on other sites

  • 2 months later...

@sirbow2

I tried the code myself, but i couldn´t solve the problem with the ㄱ⼼慶畬㹥⼼祳㹳猼ç¹ã°¾æ‘©åŒ¾ä¥”ä•â¼¼æ‘©" Code in the .txt-File, I didn´t understand where you defined the length to 300, could you tell me what exactly you have done to solve the problem?

Link to comment
Share on other sites

  • 7 months later...

Simples, to solve the ㄱ⼼慶畬㹥⼼祳㹳猼ç¹ã°¾æ‘©åŒ¾ä¥”ä•â¼¼æ‘©" problem, just change:

String data = (String)Marshal.PtrToStringAuto(map);

To...

String data = (String)Marshal.PtrToStringAnsi(map);

You can then parse the XML using whatever method floats your boat. Google is your friend.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...