tags:

views:

514

answers:

1

The case:

There is a .net application calling unmanaged C code. Used method for this:

public static class MiracleCreator
{
    [DllImport("Library.dll")]
    private static extern void RunUnmanaged(string fileName);

    public static void Run(string fileName)
    {
        RunUnmanaged(fileName);
    }
}

It is used in a Windows Forms application and the needed file name is obtained by OpenFileDialog. Code:

if (openFileDialog.ShowDialog() == DialogResult.OK)
{
    MiracleCreator.Run(openFileDialog.FileName);
}

The problem:

After several executions of the code in the Windows Forms application the openFileDialog gets broken with exception: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

In searching for solution:

Trying "more reliable" use of OpenFileDialog doesn't help. Like this solution (tried to give the link, but "new users aren't allowed to add hyperlinks" :) ):

public class Invoker
{
    public OpenFileDialog InvokeDialog;
    private Thread InvokeThread;
    private DialogResult InvokeResult;

    public Invoker()
    {
        InvokeDialog = new OpenFileDialog();
        InvokeThread = new Thread(new ThreadStart(InvokeMethod));
        InvokeThread.SetApartmentState(ApartmentState.STA);
        InvokeResult = DialogResult.None;
    }

    public DialogResult Invoke()
    {
        InvokeThread.Start();
        InvokeThread.Join();
        return InvokeResult;
    }

    private void InvokeMethod()
    {
        InvokeResult = InvokeDialog.ShowDialog();
    }
}

Usage :

        Invoker I = new Invoker();

        if (I.Invoke() == DialogResult.OK)
        {
            MessageBox.Show(I.InvokeDialog.FileName, "Test Successful.");
        }
        else
        {
            MessageBox.Show("Test Failed.");
        }

Questions:

Is the exception really caused by the unmanaged code? Could other possible problems be expected (breaking something different from the OpenFileDialog)? What is the better approach for this?

Thank you for every idea/solution.

+1  A: 

You should specify the appropriate MarshalAs attribute for the string parameter of the method declaration. Something like:

[DllImport("Library.dll")]
private static extern void RunUnmanaged(
  [MarshalAs(UnmanagedType. ... )] string fileName);
Mehrdad Afshari
Well... Trying to follow your advice but it is not easy to "guess" all needed attributes... :)The real imported method looks like: [DllImport("Library.dll")] private static extern int Run(string[] fileLines, int linesCount, string filePath, int someIntValue, ref string errorMsg, ref int refIntValue, ref string refStringValue);Tried to use UnmanagedType.LPArray for string[] and UnmanagedType.LPStr for string and ref string. Nothing got worse and nothing got better :). Please help with the correct attributes.
Alex
@Alex: Post the unmanaged signature
Mehrdad Afshari
Like Mehrdad said, the signature would help. Are you wrapping anything else, like a callback or some other function call?
R Ubben
The unmanaged signature is int __declspec(dllexport) Run(char **lines, int linesCount, char* filePath, int someIntValue, char** errorMsg, int* refIntValue, char** refStringValue) { ... }. No callback functions.
Alex