3

I am using an open file dialog which I dragged from the toolbox onto my form. The file dialog was working fine until recently.

I've searched high and low for an answer online but none of them work. I started the project on my home computer and then copied the whole project folder to my work computer so that I can work on it both at home and at work.

The file dialog works fine even now on my work computer but after I make changes to the code (at work) and copy the new project folder to my home computer the issue occurs. This is not managed in TFS or any other shared location. This is a private project that I am working on. The code where the issue occurs is as below:

Thread th;        
private void btnUploadToDB_Click(object sender, EventArgs e)
{
    try
    {

        openFileDialog1.Title = "Select new data file";
        openFileDialog1.Filter = "Excel Files |*.xlsx";

        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            string filePath = openFileDialog1.FileName;
        }
        else if (DialogResult == DialogResult.None)
        {
            return;
        }

        th = new Thread(uploadToDB);
        Control.CheckForIllegalCrossThreadCalls = false;
        th.Start();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        GC.Collect();
    }
}

The stack trace when the error occurs is as below:

System.AccessViolationException was unhandled Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Source=System.Windows.Forms StackTrace: at System.Windows.Forms.FileDialogNative.IFileDialog.Show(IntPtr parent) at System.Windows.Forms.FileDialog.RunDialogVista(IntPtr hWndOwner) at System.Windows.Forms.FileDialog.RunDialog(IntPtr hWndOwner) at System.Windows.Forms.CommonDialog.ShowDialog(IWin32Window owner) at System.Windows.Forms.CommonDialog.ShowDialog() at Form1.Form1.btnUploadData_Click(Object sender, EventArgs e) in C:\Users\User1\Documents\Visual Studio 2010\Projects\C#_Projects\C# Projects\Solution 1\Solution 1\Form1.cs:line 458 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.Run(Form mainForm) at Form1.Program.Main() in C:\Users\User1\Documents\Visual Studio 2010\Projects\C#_Projects\C# Projects\Solution 1\Solution 1\Program.cs:line 18 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

Further, I tried creating an empty project on my home computer where the issue occurs and added an openfiledialog in the same manner and it works fine. The issue seems to be with only this application and that too when it is on my home machine.

I am adding the updateToDB method as requested. I have modified some values so there might be lines that don't make sense, however, I believe it is not relevant to the issue at hand.

private void uploadToDB()
{
    try
    {
        string values = "";
        string excelConString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" +
                filePath + "'; Extended Properties='Excel 12.0 Xml;HDR=Yes;IMEX=1;'";
        string excelSql = "select * from [Sheet1$]";
        string accessConString = GlobalOleDBCommands.DBconString;

        string accessSql = "delete from table1";
        GlobalOleDBCommands.CommandExecuteNonQuery(accessSql, accessConString);

        using (OleDbDataAdapter adap = new OleDbDataAdapter(excelSql, excelConString))
        {
            using (DataTable dt = new DataTable())
            {
                adap.Fill(dt);

                using (OleDbConnection accessCon = new OleDbConnection(accessConString))
                {
                    accessCon.Open();

                    for (int i = 0; i < dt.Rows.Count - 1; i++)
                    {

                        for (int j = 0; j <= dt.Columns.Count - 1; j++)
                        {
                            values = values.Trim() + dt.Rows[i][j] + ",";
                        }
                        values = Strings.Left(values, (Strings.Len(values) - 1));

                        string value1 = SplitAndReturnText(values, ",", 0);
                        string value2 = SplitAndReturnText(values, ",", 1);
                        string value3 = SplitAndReturnText(values, ",", 2);
                        string value4 = SplitAndReturnText(values, ",", 3);

                        accessSql = "insert into table1 (value1,value2,value3,value4) values(@value1,@value2,@value3,@value4)";

                        using (OleDbCommand dtToAccessCmd = new OleDbCommand(accessSql, accessCon))
                        {
                            dtToAccessCmd.Parameters.AddWithValue("@value1", value1);
                            dtToAccessCmd.Parameters.AddWithValue("@value2", value2);
                            dtToAccessCmd.Parameters.AddWithValue("@value3", System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(value3.ToLower()));
                            dtToAccessCmd.Parameters.AddWithValue("@value4", value4);
                            try
                            {
                                dtToAccessCmd.ExecuteNonQuery();
                            }
                            catch (Exception)
                            {

                            }

                            this.lblProgress.Text = (i + "/" + ((dt.Rows.Count) - 1)).ToString();
                            this.lblProgress.Refresh();
                        }
                        // Reset value variable to null.
                        values = "";
                    }
                }
            }
        }

        accessSql = "select max(end_time) from table1 where user_name='" +
                    Environment.UserName + "'";

        DateTime start_time = Convert.ToDateTime(GlobalOleDBCommands.
        CommandExecuteScalar(accessSql, GlobalOleDBCommands.DBconString));
        DateTime end_time = DateTime.Now;
        double total_time = (end_time - start_time).TotalMinutes;

        string fieldValues = "start_time, end_time, user_name, task_name, total_time,task_count";
        accessSql = "insert into table1 (" + fieldValues + ") values ('" +
                    start_time + "','" + DateTime.Now + "','" + Environment.UserName +
                    "','Update to DB','" + total_time + "','1')";
        GlobalOleDBCommands.CommandExecuteNonQuery(accessSql, GlobalOleDBCommands.DBconString);

        MessageBox.Show("New data added ");
        this.lblProgress.Text = "";

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

Could someone please advise what is causing this issue as I am not able to work on changes to the code at home for the fear that it would not work when I transfer to my work machine.

TimothyP
  • 21,178
  • 26
  • 94
  • 142
svb
  • 85
  • 2
  • 10
  • What are the differences between the 2 machines? Same .Net framework installed? Same version of Visual Studio? Same version of Windows? 32-bit Vs. 64-bit could make a difference even. Here's a similar question with several suggestions: http://stackoverflow.com/questions/22293032/attempted-to-read-or-write-protected-memory-this-is-often-an-indication-that-oth and another: http://stackoverflow.com/questions/596413/attempted-to-read-or-write-protected-memory – Bensonius Apr 26 '15 at 07:59
  • Can you please paste the code of the `uploadToDB` method too? – keenthinker Apr 26 '15 at 08:01
  • Even if this works on one computer and not on the other, seems to me like it's pure luck. You're manually creating threads and probably accessing non thread-safe data from those other threads (not enough code here to really be sure). You're also manually calling garbage collection. I think you might want to take a step back and look at TPL (Tasks) and Async/Await. Posting more of your code might help as well – TimothyP Apr 26 '15 at 08:03
  • Maybe one of the answers here might help http://stackoverflow.com/questions/22293032/attempted-to-read-or-write-protected-memory-this-is-often-an-indication-that-oth – DeanOC Apr 26 '15 at 08:03
  • @Bensonius Both machines have same sofware installed Win 7 64 bit and .Net Framework 4. – svb Apr 26 '15 at 08:10
  • @pasty how do i upload the uploadToDB code ? in the comments? Sorry, I am new here. – svb Apr 26 '15 at 08:11
  • Maybe not relevant, but why do you have a `finally` block with `GC.Collect();` in it? – Jeppe Stig Nielsen Apr 26 '15 at 08:12
  • @JeppeStigNielsen I was just following the coding example of my seniors as i was told it was good practice to do so. Please advise if you feel this is not good practice. – svb Apr 26 '15 at 08:18
  • @TimothyP, the uploadToDB method takes the filename from the openfiledialog and creates an oledb connection to get the data into a datatable. From the datatable, I'm inserting the values using a parametrized query into an Access DB. While the insertion takes place, i have a label that shows how many records have been processed. Not using a thread would cause the UI to freeze or the updates to not occur. Hope this helps. – svb Apr 26 '15 at 08:22
  • You can add the code by editing your own question - click the `edit` link below your question. – keenthinker Apr 26 '15 at 08:24
  • 3
    Edit your question and paste it. I'm sorry to be blunt, but if your "senior" developers tell you it is good practice they should not be called "senior" developers and you need to look for better mentors. There are reasons to call GC.Collect it is not however consider good practice to always do so (http://stackoverflow.com/questions/478167/when-is-it-acceptable-to-call-gc-collect, http://stackoverflow.com/questions/118633/whats-so-wrong-about-using-gc-collect) Check that last link first! – TimothyP Apr 26 '15 at 08:27
  • 1
    Do you update your UI from the `uploadToDB` method? If so, change the line in your code `Control.CheckForIllegalCrossThreadCalls = false;` to `Control.CheckForIllegalCrossThreadCalls = true;` (or comment it out) to see if maybe you have a *classic* cross thread exception. Such problems can be solved easily (for example with `Control.Invoke` or using the [Task Parallel Library](https://msdn.microsoft.com/de-de/library/dd460717%28v=vs.110%29.aspx)) . And generally do not turn *standard* framework protection mechanisms off (as long as it's not really needed and you know what you're doing). – keenthinker Apr 26 '15 at 08:39
  • @pasty, yes a label gets updated and if i do not use Control.CheckForIllegalCrossThreadCalls = false; then it does crash with an exception. – svb Apr 26 '15 at 08:47
  • @TimothyP I've added the code for uploadToDB – svb Apr 26 '15 at 08:52
  • Have you tried changing the `string filepath` variable to one that is outside of the if-statement or as a class variable? You are referencing it inside your `uploadToDB`, which might mean that on the one system it is seen as protected memory (since the thread is started outside the if) – Bernd Linde Apr 26 '15 at 09:00
  • @pasty I've added the code for uploadToDB – svb Apr 26 '15 at 09:03
  • @BerndLinde, Yes I've tried that as well. Tried it as a class variable and also tried declaring it globally. The code still fails at the OpenFileDialog1 – svb Apr 26 '15 at 09:08
  • 1
    Exactly updating the UI (Labels, TextBoxes, MessageBox) in combination with turning off the standard protection is the problem. Turn the protection on and have a look at this SO post [Cross thread exception](http://stackoverflow.com/questions/9342747/cross-thread-exception) to see how to update UI elements from a non-UI-thread. – keenthinker Apr 26 '15 at 09:11
  • @pasty, I've removed the thread call so that the button click event only contains the openFileDialog1.Show(). I even created a new button and dragged a new openFileDialog2 and tried the same. Still it fails with the same exception. – svb Apr 26 '15 at 09:15
  • Do you have **any** custom themed items in your solution or on you home pc that is different than the work one? Is it possible to create a new user on your home pc, log in under that and see if your application then runs?runs – Bernd Linde Apr 26 '15 at 09:18
  • @pasty, I don't know if this info helps but the label is present in a tabpage of a tabcontrol on Form1 – svb Apr 26 '15 at 09:21
  • @BerndLinde, It would have made sense to try a new user but the issue is only within this application. It does not happen when I create a new Win Form application and call the openFileDialog.Show(); Other applications seem to be working fine as well where a call to openFileDialog is present. – svb Apr 26 '15 at 09:23
  • Read what @pasty said. You are updating UI elements from another thread. You should never do this, at least not directly. You should fix that before attempting to solve any other issues. – TimothyP Apr 26 '15 at 09:24
  • Calling `GC.Collect()` is certainly bad practice. But I do not think it is related to your problem. – Jeppe Stig Nielsen Apr 26 '15 at 09:30
  • One more try: Try and set the [AutoUpgradeEnabled](https://msdn.microsoft.com/en-us/library/system.windows.forms.filedialog.autoupgradeenabled%28v=vs.110%29.aspx) property to false before you call the `ShowDialog` as a test if the exception will still ocure. – Bernd Linde Apr 26 '15 at 09:30
  • @TimothyP, Fair enough, but If I remove the thread itself and then attempt to call openFileDialog, then it should work correct? In this case it doesn't. I've removed the thread call and re-build the solution but it still throws the same exception. So am I correct to assume that it is not related to the thread call? – svb Apr 26 '15 at 09:31
  • @BerndLinde, I've removed the thread and set the property to false as you advised, still the same issue. – svb Apr 26 '15 at 09:32
  • Is the excel file (excel application) still open while you try to read it? If yes, then close the file and try again to open it with the OpenFileDialog or does the application crashesh before you even select a file? – keenthinker Apr 26 '15 at 09:49
  • @pasty, the excel file in concern is not open and yes, it crashes even before i select a file. It fails at the line if (openFileDialog1.ShowDialog() == DialogResult.OK). I've tried removing the if block and calling the dialog, doesn't work. I've even tried calling it outside the try block, doesn't work. Created a new button and used a new filedialog i.e. openFileDialog2 (dragged and dropped from toolbox), doesn't work. – svb Apr 26 '15 at 09:58
  • Have you tried the empty solution with the openfiledialog, but the solution is created on your work machine and tested on your home machine? (I know you tried an empty one on your home pc) – Bernd Linde Apr 26 '15 at 10:08
  • @BerndLinde, No I haven't tried that. however, this project started on my home pc and while at work i wrote a lot of code and brought it back home. That is when I noticed the issue. Out of curiosity, what could we isolate from the step you've advised? – svb Apr 26 '15 at 10:15
  • With that, one could compare the project and design files to see if there are any settings that are set differently, which then could indicate where/why you are getting it. Your issue is intriguing – Bernd Linde Apr 26 '15 at 10:17
  • @BerndLinde, Agreed. It has baffled me for days and its after all that I decided to check for help here. I will have to try that at work and get back to you. – svb Apr 26 '15 at 10:21
  • @BerndLinde, Hi, I've done what you advised i.e. create a test solution at work and run it at home pc. guess what? it works! :( – svb Apr 29 '15 at 14:27
  • Hhmm, take your non-working project and strip out everything except the method that gives the error and a single point where it is used, remember to "Sort and Remove unused Usings". If that works, add one class at a time until it fails. From there you can then maybe determine what the issue might be – Bernd Linde Apr 29 '15 at 14:30
  • @BerndLinde, I don't this its the method. Even if I create a new button and call another openfiledialog, its the same issue. I am suspecting its the way the call is being made to System.Windows.Forms.dll. I've tried removing and re-adding the reference, that didn't help. Any other clues why I would get this message A first chance exception of type 'System.AccessViolationException' occurred in System.Windows.Forms.dll – svb Apr 29 '15 at 15:15
  • @BerndLinde, Is it possible that something in this solution only is forcing some exception, some setting perhaps? Just to keep you updated, I made changes to the solution at home and ran the new code on my work pc, it works fine without any issues. I've already tried re-setting VS2010 settings to default. Also, I use VS2010 Express at work and VS2010 Ultimate SP1 at home. – svb Apr 30 '15 at 09:40
  • Nothing that I am aware of, since the dialog you are using is a Win standard dialog and handled by the .Net framework itself. Check in the .csproj file if you have references to specific .Net DLLs (instead of Includes without a file reference). Also try and run the [.Net repair](https://www.microsoft.com/en-us/download/details.aspx?id=30135) at home (even though only this project throws the error, might be a specific DLL that only it uses is broken) – Bernd Linde Apr 30 '15 at 09:52
  • @BerndLinde, I will try the .Net repair once I am home. It doesn't specifically say if it will work on .Net 4.0 as I am using that at home. I also checked the number of references I have; there are 12 references in solution explorer and in the .csproj file but only 10 in the code area where one usually declares the namespace like using System.Windows.Forms; Do you reckon this is the problem area? Is there a way to re-create the .csproj file? – svb Apr 30 '15 at 10:49
  • @BerndLinde, I've tried using .Net repair and I've also tried creating a new user on my machine and running the code. The issue still persists. – svb May 01 '15 at 21:07
  • @TimothyP, Do you have any ideas what could be the cause? – svb May 01 '15 at 21:07
  • The only thing left that I can think of is to do what I said earlier about stripping the project down to just the single class, thereafter you can compare that with a clean, working project and see where the differences are. Other than that, without being able to replicate it locally, I am out of ideas :( – Bernd Linde May 01 '15 at 21:30
  • @BerndLinde, I tried something different and surprisingly it works in the same project but still not able to understand why it doesn't work in other button click events. What I did was is that I tried using the openfiledialog in the form load event and it works fine. It just doesn't work in the button click event. Why? – svb May 02 '15 at 05:58
  • @BerndLinde, My project contains a mainform over which I have used a tabcontrol. The buttons are present inside the tab pages of the tabcontrol, The main form is never accessed directly by the user other than to minimize or close the application. If I minimize the tabcontrol, add a button directly on the main form and call the openfiledialog, that also works fine. – svb May 02 '15 at 06:15
  • @BerndLinde, If I bring the button back onto the tabpage of the tabcontrol and call the openfiledialog it fails with the error. – svb May 02 '15 at 06:17
  • Hhmm, ok. Try to instead of using `openDialog1`, create an `OpenDialog` inside your method and use that created one instead. – Bernd Linde May 02 '15 at 09:23
  • @BerndLinde, you meant to say create something like this Openfiledialog ofd= new OpenFileDialog(); If yes, I've tried that, its the same problem. works fine when the button is directly on the form. Throws the same error when it is on the tabpage. – svb May 02 '15 at 09:33
  • Out of absolute desperation, does anyone have an idea why this is happening? I even created a test project on my home machine, added a tabcontrol to the form, button in the tabpage and called the openfiledialog to replicate the issue and could not reproduce the same issue I'm facing with this project. – svb May 04 '15 at 15:59

1 Answers1

-2

To run code on a deploy computer one of two things must occur 1) The exact same version of Net library must be on both computers including updates. 2) You must publish the application on the build computer and then run the setup.exe folder that is created on the build computer on the deploy computer.

You simply can't copy the exe from one computer to another.

jdweng
  • 33,250
  • 2
  • 15
  • 20
  • So my application is saved under Documents\Visual Studio 2010\Projects\C# Projects\Solution1. I am copying the Solution1 folder between the two machines. The same version of .Net exists on both computers. – svb Apr 26 '15 at 08:17
  • @jdweng what you have written here is not correct at all. Nor does it solve the issue at hand. – TimothyP Apr 26 '15 at 08:24
  • Tim : An exception is occurring due to an invalid pointer. If the Net Library isn't the same exceptions like this can occur. Since the code works on one computer I suspect there are differences in the Net Libraries. You need to deploy the application to get rid of the exception. – jdweng Apr 26 '15 at 12:33
  • There is no need to "publish" anything. You just need to copy/paste the main executable together with the libraries you find in the build output directory. This even works when you want to run your application on a different operating system (such as Linux). Which is what we do all the time. – TimothyP Apr 26 '15 at 14:36