MSI Afterburner .NET Class Library

Discussion in 'MSI AfterBurner Application Development Forum' started by stangowner, Feb 28, 2011.

  1. rewt

    rewt Maha Guru

    Messages:
    1,279
    Likes Received:
    15
    GPU:
    Yes
    Both ;)

    I added references to a VS 2010 C# project of mine and it worked like a charm. However at this time my project only relates to the RTSS and OSD shared memory, so I am still having to do quite a bit of work porting over Unwinder's C++ code (but overall it's much less work than rewriting my application in C++).
     
  2. Haldi

    Haldi Master Guru

    Messages:
    292
    Likes Received:
    25
    GPU:
    R9-290 CF
    Hei, I have a question.
    I'm don't realy have the knowledge on .NET Basis... but:
    Is it somehow possible to change the FPS Limiter directly ? Activate / Set Max FPS an such? That's not part of MSI Afterburner but from the rtss right?

    If no, would it be possible with the MSI Remote server to set FPS limit ?
     
  3. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    15,298
    Likes Received:
    2,597
    No, it is impossible
     
  4. stangowner

    stangowner Master Guru

    Messages:
    607
    Likes Received:
    10
    GPU:
    2xMSI N550GTX-Ti Cy II OC
    This library was updated to resolve an issue preventing changes to ControlMemory from being applied to subsequent gpus in multi-gpu systems using MSI Afterburner 2.2.0 beta 14 or later.

    Links in the first post have been updated.
     

  5. adibe

    adibe New Member

    Messages:
    1
    Likes Received:
    0
    GPU:
    nVidia GTX 680
    Hello,

    Could you please implement the frequency boost options present in the MSI Afterburner 2.2.0 beta 15?

    I want to use your library with the nVidia GeForce GTX 680, but it's frequencies are modified via dwCoreClockBoostCur and dwMemoryClockBoostCur and not dwCoreClockCur and dwMemoryClockCur.

    The actual values in MACMSharedMemory.h:
    Code:
    	//clock boost control
    
    	LONG dwCoreClockBoostCur;
    		//current core clock boost in KHz
    	LONG dwCoreClockBoostMin;
    		//minimum core clock boost in KHz
    	LONG dwCoreClockBoostMax;
    		//maximum core clock boost in KHz
    	LONG dwCoreClockBoostDef;
    		//default core clock boost in KHz
    
    	LONG dwMemoryClockBoostCur;
    		//current memory clock boost in KHz
    	LONG dwMemoryClockBoostMin;
    		//minimum memory clock boost in KHz
    	LONG dwMemoryClockBoostMax;
    		//maximum memory clock boost in KHz
    	LONG dwMemoryClockBoostDef;
    		//default memory clock boost in KHz
    Thank you.
     
    Last edited: Apr 7, 2012
  6. stangowner

    stangowner Master Guru

    Messages:
    607
    Likes Received:
    10
    GPU:
    2xMSI N550GTX-Ti Cy II OC
    I plan on adding that. But its going to be a bit before I can get to it.
     
  7. stangowner

    stangowner Master Guru

    Messages:
    607
    Likes Received:
    10
    GPU:
    2xMSI N550GTX-Ti Cy II OC
    1.1.0 Released

    This library has been updated to include the new power limit control, core clock boost control and memory clock boost control that were added in MSI Afterburner 2.2.0. The links in the first post have been updated.

    - Nick
     
  8. VultureX

    VultureX Banned

    Messages:
    2,577
    Likes Received:
    0
    GPU:
    MSI GTX970 SLI
    Nice libarary. It annoys me that Afterburner does not work in 64-bit applications. In theory one could create a costum overlay for 64-bit applications using this class library and some other APIs, which would be pretty neat, but would also cause massive overhead.

    On another note:
    Is it possible to add functionality to send commands to Afterburner, such as 'take a screenshot', 'show overlay' and such?
    I'm trying to work around an issue that prevents screenshots from being taken if Ctrl is also pressed at the same time.

    Hmm, it might be easier, but less challenging to post this in the bug thread instead, but I assume I don't have a choice. :p
     
  9. basco

    basco Member Guru

    Messages:
    130
    Likes Received:
    4
    GPU:
    560tfII
    thanks very much for your time + effort!
     
  10. stangowner

    stangowner Master Guru

    Messages:
    607
    Likes Received:
    10
    GPU:
    2xMSI N550GTX-Ti Cy II OC
    No sorry, this library can't help you with that.

    You're welcome. And as always, thanks to Unwinder for making this possible.
     

  11. easperhe

    easperhe Member

    Messages:
    15
    Likes Received:
    0
    GPU:
    nVidia / GeForce 8200
    Thanks for the effort here! I will be trying this out shortly and will provide feedback.
     
  12. easperhe

    easperhe Member

    Messages:
    15
    Likes Received:
    0
    GPU:
    nVidia / GeForce 8200
    Stangowner, All,

    I would like to open AB, set a voltage, then exit AB. And I want to do this several times within the same C# program. The problem I'm seeing is that this only works on the first instance of AB. After that, the subsequent instances of AB are not working.

    It seems like C# control memory object is updated for the 1st instance of AB but continues to point to this first instance (which really doesn't exist anymore) after that instance of AB is closed and another instance of AB is opened. See below for the core of an example C# program that shows the issue.

    How can I make this work? I can try to use just an initial instance of AB. But, I consider this less robust since AB might close of the user might accidently close AB. Since the C# code has not closed, it could open a new AB instance but this wouldn't work due to this issue.

    Thanks!


    string[] gpu_volt_values = new string[] { "1.05", "1.15", "1.20" };

    Double newDouble;
    UInt32 gpu_volt_value_new;

    foreach (string gpu_volt_value in gpu_volt_values) {

    if (Double.TryParse(gpu_volt_value, out newDouble)) {
    gpu_volt_value_new = Convert.ToUInt32(newDouble * 1000);
    try {

    // Start MSI AfterBurner
    ProcessStartInfo info = new ProcessStartInfo(@"C:\Program Files (x86)\MSI Afterburner\MSIAfterburner.exe");
    info.UseShellExecute = false;
    info.WorkingDirectory = @"C:\Program Files (x86)\MSI Afterburner";

    Process prog = Process.Start(info);
    Thread.Sleep(2000);

    // Attach to MSI AfterBurner shared memory
    macm = new ControlMemory();
    macm.Connect();

    macm.GpuEntries[0].CoreVoltageCur = gpu_volt_value_new;
    macm.CommitChanges();
    System.Threading.Thread.Sleep(2000);
    macm.ReloadAll();
    macm.Disconnect();


    } catch (Exception e) {
    Console.WriteLine(e.Message);
    }

    // Kill the MSI Afterburner task
    ProcessStartInfo info2 = new ProcessStartInfo(@"taskkill.exe");
    info2.UseShellExecute = false;
    info2.Arguments = " /F /IM " + "\"" + @"MSIAfterburner.exe" + "\"" + " /T ";

    Process prog2 = Process.Start(info2);
    prog2.WaitForExit();


    }
    }
     
  13. stangowner

    stangowner Master Guru

    Messages:
    607
    Likes Received:
    10
    GPU:
    2xMSI N550GTX-Ti Cy II OC
    Hi,

    I can't personally test this for another week or so. I'm traveling in Europe right now and I don't have access to my home PC.

    A few things to note though:

    1. There is no need to call macm.ReloadAll(), because you are just disconnecting right afterwards. You don't need to refresh all the properties in the object..... it is just wasting a few clock cycles
    2. You should not just kill MSI Afterburner like that. It is not letting the application do its proper shutdown procedure, which includes removing the shared memory (or flagging it as dead if other apps have a handle open to it)
    3. Are you sure that 2 seconds is long enough for Afterburner to start before using this library?
    Let me know your thoughts on the above, and/or if you do more testing/changes before I return home.

    Thanks,
    Nick
     
  14. easperhe

    easperhe Member

    Messages:
    15
    Likes Received:
    0
    GPU:
    nVidia / GeForce 8200
    Stangowner,

    Below are answers to your thoughts. For how, I'll keeping MSI AB open all the time. I start it at windows startup and keep it minimized in the taskbar so the user doesn't see it. This is OK for now. But, I would like to figure out how to get this to work properly if MSI AB does die for some reason and I have to relaunch MSI AB.

    Thanks, easperhe


    1. There is no need to call macm.ReloadAll(), because you are just disconnecting right afterwards. You don't need to refresh all the properties in the object..... it is just wasting a few clock cycles

    -- OK. I was just trying everything to see is something worked.

    2. You should not just kill MSI Afterburner like that. It is not letting the application do its proper shutdown procedure, which includes removing the shared memory (or flagging it as dead if other apps have a handle open to it)

    -- How do you suggest shutting down MSI AB?

    3. Are you sure that 2 seconds is long enough for Afterburner to start before using this library?

    -- I've had no problems so far.
     
  15. stangowner

    stangowner Master Guru

    Messages:
    607
    Likes Received:
    10
    GPU:
    2xMSI N550GTX-Ti Cy II OC
    I'm not sure if there is a command line argument for that. I tried the basics (/x, /q, /exit, /quit) and none of them worked. Perhaps Unwinder can tell us if there is an argument to exit the application.

    - Nick
     

  16. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    15,298
    Likes Received:
    2,597
    There is no such command line switch, Nick.
     
  17. stangowner

    stangowner Master Guru

    Messages:
    607
    Likes Received:
    10
    GPU:
    2xMSI N550GTX-Ti Cy II OC
    Thanks for the reply!

    Sorry, but I don't have a good suggestion for this.
     
  18. danielkza

    danielkza New Member

    Messages:
    8
    Likes Received:
    0
    GPU:
    Shappire HD4830
    Sending a WM_QUIT message to Afterburner should be enough.

    ---

    Now for my own issue: I just recently changed from an MSI GTX 570 to an MSI NGTX680 Lightning, and I cannot get an accurate memory amount through the .NET API. I always get a value of 0.

    I'm using Powershell, and everything seems to work fine, except for retrieving the memory amount (which is unfortunately critical for my program). Here is a simple test script, followed by it's output (you need to place the API DLL in the same folder as the script):

    Code:
    $baseFolder = Split-Path -parent $script:MyInvocation.MyCommand.Path
    
    Add-Type -Path $baseFolder\MSIAfterburner.NET.dll
    
    $cmem = New-Object MSI.Afterburner.ControlMemory
    Write-Host ("MSI Afterburner (API version {0})" -f $cmem.Header.GetVersionText())
        
    $hmon = New-Object MSI.Afterburner.HardwareMonitor
    
    foreach($gpu in $hmon.GpuEntries)
    {
        Write-Host ("GPU #{0}" -f ($gpu.Index+1))
        Write-Host ("  Device: {0}" -f $gpu.Device)
        Write-Host ("  Driver Version: {0}" -f $gpu.Driver)
         Write-Host ("  Memory: {0}" -f ($gpu.MemAmount))
    }
    
    Code:
    MSI Afterburner (API version 2.0)
    GPU #1
      Device Version: MSI N680GTX Lightning
      Driver: 310.70
      Memory: 0MB
    
    Can anyone reproduce this issue with other cards?

    Thanks,
    Daniel
     
    Last edited: Jan 21, 2013
  19. timiman

    timiman Member

    Messages:
    42
    Likes Received:
    1
    GPU:
    2xR9-290 Asus DCU-II
    I'm having a scenario in which I came along using the .dll .

    1.MSI Afterburner is already running.
    2.My application (.net vb) starts.
    -Recognizes all data from .dll and can get values
    3.MSI Afterburner closes.
    4.Try to retrieve again from the .dll the MSIAfterburner data, and gets nothing.
    5.Re-open MSIAfterburner
    6.Try to retrieve again from the .dll and I get a message of "Connected to a shared memory that is flagged dead".

    Only reopening my application fixes the issue, but it has to be something that I'm doing wrong here.

    My code is like that:
    Code:
        Sub Find_Avail_GPUS()
            Try
                Dim HardwareMonitorMSIAft = New HardwareMonitor
                Form1.gpus_found = HardwareMonitorMSIAft.GpuEntries.Count
                HardwareMonitorMSIAft = Nothing
            Catch ex As Exception
                Form1.gpus_found = 0
            End Try
        End Sub
    
    The exception happens when I'm trying to "Dim HardwareMonitorMSIAft..." on step 6. Firstly, I thought that by using a "HardwareMonitorMSIAft=nothing" on "Catch" will be fine, but the scope of the HardwareMonitorMSIAft wont get inside "Catch". Then, I've tried with a global HardwareMonitorMSIAft to overcome the scope problem, but then the exception happens if my application starts and MSIAfterburner is not running.

    Is there a more "handled" and "crash-free" approach to check if MSIAfterburner is running or not? Because the declaration "Dim HardwareMonitorMSIAft = New HardwareMonitor" is trying to connect also, if I'm getting it correctly.

    Thanks in advance.
     
  20. stangowner

    stangowner Master Guru

    Messages:
    607
    Likes Received:
    10
    GPU:
    2xMSI N550GTX-Ti Cy II OC
    Hi Timiman,

    There is a Disconnect() method which releases the handle to shared memory. Try calling that before you set the HardwareMonitorMSIAft object to nothing. I think the handle to shared memory is being left open when you set the HardwareMonitorMSIAft object to nothing. You don't need to call Connect(), because the constructor already calls that and populates the classes.

    I think the root issue is I don't have the proper destructor for that class in place. The destructor should release the file handle if it is still valid, so you don't have to call Disconnect() explicitly. I'll look at updating that.

    Concerning the question on the trapping the error, can't you just define your variable outside the try block, but not initialize it until you are in the block?
    Code:
    Dim HardwareMonitorMSIAft
    Try
        HardwareMonitorMSIAft = New HardwareMonitor
        ...
    Catch ex As Exception
        ...
    End Try
    I raise errors if the class initialization can not connect to Afterburner's shared memory, so you should be able to catch those and take appropriate action. This includes when Afterburner is not running.

    Thanks,
    Nick
     

Share This Page