3

I have used the code below for my SAP Business One add-on that reads Excel sheets from a dialog box. While testing my addon, I placed a breakpoint at

Thread.Sleep(1);  // Wait a sec more

in Visual Studio 2012. This enables the dialog box to open so that I can select the Excel file because in SAP

  1. The dialog must be run on a separate thread.
  2. The dialog must be modal for the correct instance of the SAP client window.

While debugging/testing in Visual Studio, the addon runs fine and can select an Excel sheet which copies to a matrix. However, when I make an .ard with .exe file to register in SAP (an executable file), the addon hangs soon after I choose an excel file (press OK) on the dialog box.

What am I doing wrong in the code?#

private void GetFileHeader()
        {
            using (GetFileNameClass oGetFileName = new GetFileNameClass())
            {
                oGetFileName.Filter = "Excel files (*.csv)|*.csv";
                oGetFileName.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                Thread threadGetExcelFile = new Thread(new ThreadStart(oGetFileName.GetFileName));
                threadGetExcelFile.SetApartmentState(ApartmentState.STA);

                try
                {
                    threadGetExcelFile.Start();
                    while (!threadGetExcelFile.IsAlive) ; // Wait for thread to get started
                    Thread.Sleep(1); // Wait a sec more
                    threadGetExcelFile.Join(); // Wait for thread to end

                    var fileName = string.Empty;
                    fileName = oGetFileName.FileName;

                    if (fileName != string.Empty)
                    {
                        string connString = "";
                        System.Data.DataTable dt = new System.Data.DataTable();

                        // Initialize connection string
                        connString = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;HDR=YES\"", fileName);

                        // Connect
                        OleDbConnection myConnection = new OleDbConnection(connString);

                        // Open connection if closed
                        if (myConnection.State != ConnectionState.Open)
                            myConnection.Open();

                        string fName = fileName;

                        fName = System.IO.Path.GetFileNameWithoutExtension(fName);

                        string sql = "SELECT * FROM [" + fName + "$] WHERE RecordKey IS NOT NULL";

                        OleDbCommand cmd = new OleDbCommand(sql, myConnection);
                        cmd.CommandType = CommandType.Text;

                        OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);

                        adapter.Fill(dt);

                        if (dt != null)
                        {

The GetFileNameClass

using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;

namespace SBOPlugins.Enumerations
{
    public enum eFileDialog { en_OpenFile = 0, en_SaveFile = 1 };
}

namespace CoreFrieght_Intraspeed
{

    /// <summary>
    /// Wrapper for OpenFileDialog
    /// </summary>
    public class GetFileNameClass : IDisposable
    {
        #region The class implements FileDialog for open in front of B1 window

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        System.Windows.Forms.FileDialog _oFileDialog;

        // Properties
        public string FileName
        {
            get { return _oFileDialog.FileName; }
            set { _oFileDialog.FileName = value; }
        }

        public string[] FileNames
        {
            get { return _oFileDialog.FileNames; }
        }

        public string Filter
        {
            get { return _oFileDialog.Filter; }
            set { _oFileDialog.Filter = value; }
        }

        public string InitialDirectory
        {
            get { return _oFileDialog.InitialDirectory; }
            set { _oFileDialog.InitialDirectory = value; }
        }

        //// Constructor
        //public GetFileNameClass()
        //{
        //    _oFileDialog = new OpenFileDialog();
        //}

        // Constructor
        public GetFileNameClass(SBOPlugins.Enumerations.eFileDialog dlg)
        {
            switch ((int)dlg)
            {
                case 0: _oFileDialog = new System.Windows.Forms.OpenFileDialog(); break;
                case 1: _oFileDialog = new System.Windows.Forms.SaveFileDialog(); break;
                default: throw new ApplicationException("GetFileNameClass Incorrect Parameter");
            }
        }

        public GetFileNameClass()
            : this(SBOPlugins.Enumerations.eFileDialog.en_OpenFile)
        {

        }

        // Dispose
        public void Dispose()
        {
            _oFileDialog.Dispose();
        }

        // Methods

        public void GetFileName()
        {
            IntPtr ptr = GetForegroundWindow();

            WindowWrapper oWindow = new WindowWrapper(ptr);

            if (_oFileDialog.ShowDialog(oWindow) != System.Windows.Forms.DialogResult.OK)
            {
                _oFileDialog.FileName = string.Empty;            
            }
            oWindow = null;
        } // End of GetFileName

        #endregion

        #region WindowWrapper : System.Windows.Forms.IWin32Window

        public class WindowWrapper : System.Windows.Forms.IWin32Window
        {
            private IntPtr _hwnd;

            // Property
            public virtual IntPtr Handle
            {
                get { return _hwnd; }
            }

            // Constructor
            public WindowWrapper(IntPtr handle)
            {
                _hwnd = handle;
            }
        }
        #endregion
    }
}

Any help appreciated.

Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
Kinyanjui Kamau
  • 1,890
  • 10
  • 55
  • 95

1 Answers1

0

The simplest thing you can do is to not to create a new thread, but instead, in the method GetFileHeader(), call oGetFileName.GetFileName() directly.

The new thread is not needed because it seems that the intent is that the application should wait until the file is chosen anyway.

Hope this helps Fredrik

Fredrik
  • 91
  • 3
  • I tried doing away with the thread and calling oGetFileName directly. I made and .ard file and executable. When I run the program now, nothing happens when I click on the button to open dialog. I believe that for SAP, the dialog must be run on a separate thread. – Kinyanjui Kamau Jun 20 '13 at 11:34