File Access Exception

File Access Exception

Nathan.HilsonN67V6
Advocate Advocate
1,050 Views
9 Replies
Message 1 of 10

File Access Exception

Nathan.HilsonN67V6
Advocate
Advocate

Running into an issue where the txt file is unable to be accessed but i can still push things to the folder. I have admin rights on everything and pushed admin rights to the application. Not sure if it is code related. 

 

JtWindowHandle: 

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace ScheduleData
{
    /// <summary>
    /// Wrapper class for converting 
    /// IntPtr to IWin32Window.
    /// </summary>
    public class JtWindowHandle : IWin32Window
    {
        IntPtr _hwnd;

        public JtWindowHandle(IntPtr h)
        {
            Debug.Assert(IntPtr.Zero != h,
              "expected non-null window handle");

            _hwnd = h;
        }

        public IntPtr Handle
        {
            get
            {
                return _hwnd;
            }
        }
    }
}

 

Command: 

 

#region Namespaces
using System.IO;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Autodesk;
using Autodesk.Revit;
using Autodesk.Revit.DB.Structure;
using TpMechanical.TpMechanical.Forms;
using System.Linq.Expressions;
#endregion

namespace ScheduleData
{
    
    [Transaction(TransactionMode.ReadOnly)]
    public class ScheduleDataCommand : IExternalCommand
    {
       
        /// <summary>
        /// Define the schedule export folder.
        /// All existing files will be overwritten.
        /// </summary>
        const string _export_folder_name
          = "C:\\tmp\\schedule_data";

        /// <summary>
        /// Schedule export filename extension.
        /// </summary>
        const string _ext = ".txt";

        const string _caption_prefix
          = "Schedule Data - ";

        /// <summary>
        /// Select a text file in the gioven folder.
        /// </summary>
        /// <param name="folder">Initial folder.</param>
        /// <param name="filename">Selected filename on success.</param>
        /// <returns>Return true if a file was successfully selected.</returns>
        static bool FileSelect(
          string folder,
          out string filename)
        {
                folder = Path.GetDirectoryName(folder);
                OpenFileDialog dlg = new OpenFileDialog();
                dlg.Title = "Select Schedule Data File";
                dlg.CheckFileExists = true;
                dlg.CheckPathExists = true;
                //dlg.RestoreDirectory = true;
                dlg.InitialDirectory = folder;
                dlg.Filter = ".txt Files (*.txt)|*.txt";
                bool rc = (DialogResult.OK == dlg.ShowDialog());
                filename = dlg.FileName;
                return rc;
        }
        void DisplayScheduleData(
          string filename,
          IWin32Window owner)
        {
            ScheduleDataParser parser
              = new ScheduleDataParser(filename);

            System.Windows.Forms.Form form
              = new System.Windows.Forms.Form();
            form.Size = new Size(400, 400);
            form.Text = _caption_prefix + parser.Name;

            DataGridView dg = new DataGridView();
            dg.AllowUserToAddRows = false;
            dg.AllowUserToDeleteRows = false;
            dg.AllowUserToOrderColumns = true;
            dg.Dock = System.Windows.Forms.DockStyle.Fill;
            dg.Location = new System.Drawing.Point(0, 0);
            dg.ReadOnly = true;
            dg.TabIndex = 0;
            dg.DataSource = parser.Table;
            dg.Parent = form;
            dg.IsAccessible= true;

            form.ShowDialog(owner);
        }

        public Result Execute(
          ExternalCommandData commandData,
          ref string message,
          ElementSet elements)
        {
                IWin32Window revit_window
                  = new JtWindowHandle(
                    Process.GetCurrentProcess().MainWindowHandle);

                UIApplication uiapp = commandData.Application;
                UIDocument uidoc = uiapp.ActiveUIDocument;
                Document doc = uidoc.Document;

                FilteredElementCollector col
                  = new FilteredElementCollector(doc)
                    .OfClass(typeof(ViewSchedule));

                ViewScheduleExportOptions opt
                  = new ViewScheduleExportOptions();

                    foreach (ViewSchedule vs in col)
                    {
                        Directory.CreateDirectory(
                         _export_folder_name);

                        vs.Export(_export_folder_name,
                        vs.Name + _ext, opt);
                    }    
                    
                string filename;

                while (FileSelect(_export_folder_name,
                  out filename))
                {
                    DisplayScheduleData(filename,
                      revit_window);
                }
                return Result.Succeeded;
        }
    }
}

 

DataParse: 

 

using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;

namespace ScheduleData
{
    class ScheduleDataParser
    {
        /// <summary>
        /// Default schedule data file field delimiter.
        /// </summary>
        static char[] _tabs = new char[] { '\t' };

        /// <summary>
        /// Strip the quotes around text strings 
        /// in the schedule data file.
        /// </summary>
        static char[] _quotes = new char[] { '"' };

        string _name = null;
        DataTable _table = null;

        /// <summary>
        /// Schedule name
        /// </summary>
        public string Name
        {
            get { return _name; }
        }

        /// <summary>
        /// Schedule columns and row data
        /// </summary>
        public DataTable Table
        {
            get { return _table; }
        }

        public ScheduleDataParser(string filename)
        {
            StreamReader stream = File.OpenText(filename);

            string line;
            string[] a;

            while (null != (line = stream.ReadLine()))
            {
                a = line
                  .Split(_tabs)
                  .Select<string, string>(s => s.Trim(_quotes))
                  .ToArray();

                // First line of text file contains 
                // schedule name

                if (null == _name)
                {
                    _name = a[0];
                    continue;
                }

                // Second line of text file contains 
                // schedule column names

                if (null == _table)
                {
                    _table = new DataTable();

                    foreach (string column_name in a)
                    {
                        DataColumn column = new DataColumn();
                        column.DataType = typeof(string);
                        column.ColumnName = column_name;
                        _table.Columns.Add(column);
                    }

                    _table.BeginLoadData();

                    continue;
                }

                // Remaining lines define schedula data

                DataRow dr = _table.LoadDataRow(a, true);
            }
            _table.EndLoadData();
        }
    }
}

 

 

 

 

0 Likes
Accepted solutions (2)
1,051 Views
9 Replies
Replies (9)
Message 2 of 10

RPTHOMAS108
Mentor
Mentor
Accepted solution

You are not closing the StreamReader.

 

Call 'Close' on it and also best to use a using statement, since you can as TextReader implements IDisposable.

 

 

Message 3 of 10

Nathan.HilsonN67V6
Advocate
Advocate

No luck. Still Getting This error. 

 

NathanHilsonN67V6_0-1669853830937.png

 

0 Likes
Message 4 of 10

RPTHOMAS108
Mentor
Mentor

Only a few things I can suggest.

 

Check the folder is being created

Don't call Directory.Create repeatedly (create it once outside for each loop).

Try inputting path into export function with '\\' at end, some things are more pedantic than Windows in terms of distinguishing directories.

Try creating file manually in that location

It might also be the export function being called repeatedly, these things they hold onto resources, see if ViewSchedule.Dispose helps (although that is a long shot perhaps).

 

Message 5 of 10

Nathan.HilsonN67V6
Advocate
Advocate

Tried them all & still the same issue. 

 

NathanHilsonN67V6_0-1669913789106.png

 

 

This is where I'm at currently. I moved the directory creation outside of the loop as well.

 

                    foreach (ViewSchedule vs in col)
                    {
                            if (vs == null)
                            { 
                                continue; 
                            }
                            
                        vs.Export(_export_folder_name,
                        vs.Name + _ext, opt);  
                        vs.Dispose();
                
                    }

 

 

Message 6 of 10

RPTHOMAS108
Mentor
Mentor
Accepted solution

Can you also confirm if it is happening on the first iteration of the loop i.e. is anything being created in the folder?

 

Also how is the view schedule named?

 

I remember going back a few years I had a similar issue exporting dwgs that had shared images. Revit would hold onto the image so next time it was exported again it wouldn't overwrite.

 

The only workaround was to create the file in a uniquely named folder and then copy it on elsewhere. Then try to look for and delete the mess left behind the next time the routine was run.

Message 7 of 10

Nathan.HilsonN67V6
Advocate
Advocate

Looks like the folder is being created & accessed which makes less sense to me if the resources aren't being held. 

NathanHilsonN67V6_0-1669928111944.png

 

I'm using the Revit SDK "Schedule Data" as a starting point & manipulating as needed if that helps as far as troubleshooting. 

Message 8 of 10

RPTHOMAS108
Mentor
Mentor

Try adding delay between exports to see if it is a latency issue or not.

Message 9 of 10

Nathan.HilsonN67V6
Advocate
Advocate

Nope. Is it possible that something is incorrect in the file select method? 

 

        /// <summary>
        /// Select a text file in the gioven folder.
        /// </summary>
        /// <param name="folder">Initial folder.</param>
        /// <param name="filename">Selected filename on success.</param>
        /// <returns>Return true if a file was successfully selected.</returns>
        static bool FileSelect(
          string folder,
          out string filename)
        {
                folder = Path.GetDirectoryName(folder);
            OpenFileDialog dlg = new OpenFileDialog
            {
                Title = "Select Schedule Data File",
                CheckFileExists = true,
                CheckPathExists = true,
                RestoreDirectory = true,
                InitialDirectory = folder,
                Filter = ".txt Files (*.txt)|*.txt"
            };
            bool rc = (DialogResult.OK == dlg.ShowDialog());
                filename = dlg.FileName;
                return rc;
        }
0 Likes
Message 10 of 10

Nathan.HilsonN67V6
Advocate
Advocate

Got rid of the loop completely & it worked. You were right about it holding it. Thanks for the help!

0 Likes