2017년 3월 27일 월요일

[Inno setup] How to make a script that need no answer to select a destination directory.

If you want to make a inno setup script that need no answer to select a destination directory, you have to insert a following code in the [Setup] section.

[Setup]
DisableDirPage=yes

Then setup will make a destination directory automatically.

[Civil3D API] How to make autoloading install file for .NET assembly.

There are some way to make a autoloading install for .NET assembly.
1. The way to use .lsp file at startup.
2. The way to use PackageContents.xml at startup.

Now I will explain about second way.
Second way is most new way and recommanded way.

First, PackageContents.xml file has to be in ***.bundle directory in the %appdata%Autodesk/ApplicationPlugins.

And Other needed files like .dll or .png are in the ***.bundle directory or sub directory of one.

Most important things are  directory name and contents of PackageContents.xml.
Directory name has to include .bundle at the last.
packageContents.xml file has to include information about command what you need.
Last, if you want to make ribbon at loading assembly(.dll), you have to observe the following rule.
Rule.
  - You have to call a function to make ribbon at startup when SystemVariableChanged event is happened. And you have to delete that event handler method.
  - Reference following codes.
  public class InitializeKoreaModule : IExtensionApplication
    {
        public void Initialize()
        {
            Autodesk.AutoCAD.ApplicationServices.Application.SystemVariableChanged += Application_SystemVariableChanged;
        }

        void Application_SystemVariableChanged(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs e)
        {
            if (Autodesk.Windows.ComponentManager.Ribbon != null)
            {
                //ok, create Ribbon
                LoadRibbon();
                //and remove the event handler
                Autodesk.AutoCAD.ApplicationServices.Application.SystemVariableChanged -= Application_SystemVariableChanged;
            }
        }

        public void Terminate()
        {

        }

        public void LoadRibbon()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;

            RibbonTab rbTabKorea = CreateRibbon("Korea");
            if (rbTabKorea == null)
            {
                return;
            }

            RibbonPanelSource rbPanelSuperelevation = CreateButtonPannel("Superelevation", rbTabKorea);
            if (rbPanelSuperelevation != null)
            {
                rbPanelSuperelevation.Items.Add(CreateButton("Superelevation\nPlanar Figure", "SPF", "HangilIT.C3DCountryKit.Resources.product-icon.png"));
//                rbPanelSuperelevation.Items.Add(new RibbonRowBreak());
            }

            RibbonPanelSource rbPanelEarthWork = CreateButtonPannel("Earth Work Carried Quantities", rbTabKorea);
            if (rbPanelEarthWork != null)
            {
                rbPanelEarthWork.Items.Add(CreateButton("Earth Work\nCalculation", "ECC", "HangilIT.C3DCountryKit.Resources.product-icon.png"));
                rbPanelEarthWork.Items.Add(CreateButton("Mass Curve", "MC", "HangilIT.C3DCountryKit.Resources.product-icon.png"));
                rbPanelEarthWork.Items.Add(CreateButton("Mass Haul", "MH", "HangilIT.C3DCountryKit.Resources.product-icon.png"));
            }
        }

        private RibbonTab CreateRibbon(string str)
        {
            // 리본 컨트롤 생성
            RibbonControl rc = ComponentManager.Ribbon;

            // 리본 탭 검색
            RibbonTab rt = rc.FindTab(str);
            if (rt == null)
            {
                // 리본 탭 생성
                rt = new RibbonTab();
                // 리본탭 정보
                rt.Title = str;
                rt.Id = str;
                // 리본 컨트롤에 리본탭 추가
                rc.Tabs.Add(rt);
            }
            
            // 리본탭 활성화
            rt.IsActive = true;

            return rt;
        }

        private RibbonPanelSource CreateButtonPannel(string str, RibbonTab rtab)
        {
            // 리본 패널 소스 생성
            RibbonPanelSource bp = new RibbonPanelSource();
            // 리본 패널 소스 정보
            bp.Title = str;
            // 리본 패널 생성
            RibbonPanel rp = new RibbonPanel();
            // 리본 패널에 리본 패널 소스 추가
            rp.Source = bp;
            // 리본 탭에 리본 패널 추가
            rtab.Panels.Add(rp);

            return bp;
        }

        private RibbonButton CreateButton(string str, string CommandParameter, string pngFile)
        {
            // 리본 버튼 생성
            RibbonButton button = new RibbonButton();
            // 리본 버튼 정보
            button.Text = str;
            button.Id = str;
            button.CommandParameter = CommandParameter; // name of the command
            button.ShowImage = true;
            button.ShowText = true;
            button.Size = RibbonItemSize.Large;
            button.Orientation = Orientation.Vertical;
            button.LargeImage = UtilityEtc.LoadImage(pngFile);
            // to add command to the button write the line below
            button.CommandHandler = new AdskCommandHandler();

            return button;
        }
    }


Detail information about PackageContents.xml file is in following link.
http://adndevblog.typepad.com/autocad/2013/01/autodesk-autoloader-white-paper.html


2017년 3월 25일 토요일

[Development story] GFtp #6 - To add favorites tree and etc...

GFtp is done basic functions.
So from now I will add some convenient functions. I added a favorites function today.
A tree view for favorites is made by TreeView that System.Windows.Forms provide.
File format for save favorites items is XML and to save XML I used a XMLWriter and to load XML I used a XMLReader.
XMLReader and XMLWriter was very useful for XML control.

1. Update lists

 - Added add favorites,
 - Added delete favorites.
 - Seperated ftp address and port and path.

2. GFtp v1.4 demo

3. Code snippets

 - Extend method defines

  - The extend method in C# is very useful. To make customized control, you don't have to make new custom control class what is Inherited existed control.
  - TreeView control Helper for favorites tree view
  - To make extend method, Just remember just two things that static and this.
  - Following is extend method for TreeView control for favorites.

    static public class FavoritesTreeViewHelper
    {
        // Save favorites items from favorites.xml file.
        static public bool SaveFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Load favorites items from favorites.xml file.
        static public bool LoadFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Refresh favorites items
        static public void RefreshFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Get selected favorites item
        static public FavoritesItem GetSelectedFavoritesItem(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Get selected favorites item group name
        static public string GetSelectedFavoritesItemGroupName(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Delete selected favorites item 
        static public bool DeleteSelectedFavoritesItem(this TreeView treeView, Favorites favorites)
        {
          ...
        }
    }

 - Following is way to call extend method.

   - You can call it like a member method.
  favoritesTreeView.SaveFavoritesItems(_favorites);
  favoritesTreeView.DeleteSelectedFavoritesItem(_favorites);
  favoritesTreeView.RefreshFavoritesItems(_favorites);
  favoritesTreeView.LoadFavoritesItems(_favorites);
   - You can make a extend method that has return value.
  string groupName = favoritesTreeView.GetSelectedFavoritesItemGroupName(_favorites);


- XML Reader

  - Following is GFtp's favorites structure.
   - Root elementis is <Favorites> and <Favorites> has some <Group> elements.
     And <Group> element has some <Item> element.
     <Item> element has attributes that are name, address, port, path, id, password.
   - The extend method for loading favorites.xml file.
     I called just XmlReader.Read() and XmlReader.GetAttribute(...) method.
     It's very useful for simple and small xml file. but For big xml file, you need more method in XmlReader, or you can use other class for xml like XmlDocument.

        // Load favorites items from favorites.xml file.
        static public bool LoadFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            XmlReaderSettings setting = new XmlReaderSettings();
            setting.IgnoreWhitespace = true;  // Remove all unnecessary white spaces in the xml file.
            setting.ConformanceLevel = ConformanceLevel.Fragment;

            try
            {
                List<FavoritesItem> items   = null;
                using (XmlReader reader = XmlReader.Create("favorites.xml", setting))
                {
                    while (reader.Read())
                    {
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            if (reader.Name == "Group")
                            {
                                items = favorites.GetGroup(reader.GetAttribute("name"));
                                continue;
                            }

                            if (reader.Name == "Item")
                            {
                                if(items == null)
                                {
                                    continue;
                                }

                                FavoritesItem item  = new FavoritesItem();
                                
                                item.Name   = reader.GetAttribute("name");
                                item.Address = reader.GetAttribute("address");
                                item.Port = reader.GetAttribute("port");
                                item.Path = reader.GetAttribute("path");
                                item.ID = reader.GetAttribute("id");
                                item.Password   = reader.GetAttribute("password");
                                
                                items.Add(item);
                            }
                        }

                    }
                }
            }
            catch
            {
                MessageBox.Show("Not found favorites.xml");
            }
            return true;
        }

   - Next is extend method to save savorites items to xml file.

     Because it is very simple and small xml file, I used the XmlWriter.

        // Save favorites items from favorites.xml file.
        static public bool SaveFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            XmlWriterSettings setting = new XmlWriterSettings();
            setting.Indent = true;

            try
            {
                List<FavoritesItem> items = null;
                using (XmlWriter writer = XmlWriter.Create("favorites.xml", setting))
                {
                    writer.WriteStartElement("Favorites");

                    foreach(var group in favorites._group)
                    {
                        string groupName = group.Key;
                        writer.WriteStartElement("Group");
                        writer.WriteAttributeString("name", groupName);

                        foreach(var item in group.Value)
                        {
                            writer.WriteStartElement("Item");
                            writer.WriteAttributeString("name", item.Name);
                            writer.WriteAttributeString("address", item.Address);
                            writer.WriteAttributeString("port", item.Port);
                            writer.WriteAttributeString("path", item.Path);
                            writer.WriteAttributeString("id", item.ID);
                            writer.WriteAttributeString("password", item.Password);
                            writer.WriteEndElement();
                        }
                        writer.WriteEndElement();

                    }

                    writer.WriteEndElement();
                }
            }
            catch
            {
                MessageBox.Show("Not found favorites.xml");
            }
            return true;
        }

 - Logic to add favorites and to delete favorites.

   - To add favorites : 
       - Clicks add button.
       - New item is added to favorites data class.
       - The favorites data class is saved to xml file.
       - Favorites tree view control is refreshed using favorites data class.
       
   - To delete favorites.
       - Clicks del button.
       - Finds favorites item in the favorites data class by selected item in favorites tree view cocntrol.
       - Deletes favorites item in the favorites data class.
       - The favorites data class is saved to xml file.
       - Favorites tree view control is refreshed using favorites data class.


4. Next

   - Now GFtp is became so big and complex.
     And GFtp is done almost basic function. So I will update GFtp for powerful and stability.
     I will try speed up translate using multi threading. By the way I don't know what I can do it.

2017년 3월 23일 목요일

[Civil3D API] After loading .NET dll, If Civil3D doesn't work finish.

After you call StartTransaction function, if you don't commit then Civil3D doesn't work finish.
So you can use StartTransaction like following.

using (Transaction ts = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction())
{
     ... 
     ...
}

When you use using statement. Transaction.commit() is called automatically at the end of block.


2017년 3월 20일 월요일

[C#] To check if string includes "ftp://" using Regex.

string s = "ftp://127.0.0.1:6000";

bool isInclude = System.Text.RegularExpressions.Regex.IsMatch("^ftp://", s);

If s include "ftp://" at first, then isInclude is true.

[Development story] GFtp #5 - To add explorer using open source.

GFtp is became more pretty than before. But It needs become more pretty and more easy.
Specially, moving between directories is pretty uncomfortable. So I decided to get open source like explorer tree control for that. My favorite site for open source is CodeProject.
CodeProject has so many open source and good article. To beginner like me, that is that best place.
I found a good control. Follow is link of that.

https://www.codeproject.com/Articles/14570/A-Windows-Explorer-in-a-user-control

First of all, I thanks to Raj Lal who made this control.

1. Update list

 - Added explorer Tree using open source.
 - Relayouts all controls.

2. GFtp v1.3 demo


3. To add explorer Tree 

  To add this control, C# needs only .dll file.
  C++ needs .h and .dll files.
  I am satisfied with C# useful.
  At first, you have to add user control(.dll) so you can use a user control on the form.
  Following is how to add user control(.dll).
   - Right click on the All Windows Forms of the Toolbox.
   - Click menu Choose Items...
   - Select .dll file after Browse button click.
   - Select user control.
   - Click OK button.
   - Done.
   
 To use user control, just drag&drop from the Toolbox to your Form.
 If you feel difficult to find ExplorerTree in the Toolbox, search Toolbox.

 User control what I added is shaped like following.


  I added it on the GFtp like that.




   Following code is to apply ExplorerTree(usercontrol) to GFtp.
   If you double click the ExplorerTree(user control), PathChanged event method is made automatically.

        // Called when changed path on explorerTree
        private void explorerTree_PathChanged(object sender, EventArgs e)
        {
            CurrentDirectory = explorerTree.SelectedPath;
            RefreshFileGridViewOfCurrentDirectory();
        }

  I just call explorerTree.SelectedPath method and set string to CurrentDirectory property.
  And done with calling RefreshFileGridViewOfCurrentDirectory().

4. Next

 I can't test upload yet cause I can't find Ftp server to upload.
 So I will make Ftp server to upload test.


This source is shared.
GitHub : https://github.com/gurum77/GFtp

  









2017년 3월 14일 화요일

[C#] To read a text file

// Opens a file using File.OpenText and closes a file using Dispose()
static void ReadFile()
{
     StreamReader reader = null;
     try
     {
           reader     = File.OpenText("d:\\file.txt");
           if(reader.EndOfStream)
                return;
           Console.WriteLine(reader.ReadToEnd());
     }
     finally
     {
           if(reader != null)
                reader.Dispose();
     }

}

2017년 3월 12일 일요일

[Development story] GFtp - #4 Refactoring and Git

GFtp is taken first refactoring.
At first, I thought that this is for just studying C#. So I was coding without design.
At the end, GFtp's source code is getting more dirty. And I decided to refactoring.

1. UML

 - I made some classces for modulize and small cs files.
   Almost source codes was included in Form1.cs file. But Form1.cs file is worng name and become very big. So I designed FileGridViewHelper and FtpController.
  FileGridViewHelper has 2 extend method of DataGridView control.
  FtpController has some method and property for Ftp.
  Form1 is renamed to MainForm. Form1 was made by Visual Studio wizard.
  Following is UML for that.



2. Code snippet

 - The extend method for getting selected files in the DataGridView

     - define
    // Helper class for FileGridView
    static class FileGridViewHelper
    {
        // Get file names selected in the grid view
        static public string[] GetSelectedFiles(this DataGridView gridView)
        {
            string[] files = new string[gridView.SelectedRows.Count];
            int idx = 0;
            foreach (DataGridViewRow row in gridView.SelectedRows)
            {
                files[idx++] = row.Cells[0].Value.ToString();
            }

            return files;
        }
    }

    - call
    string[] files = fileGridView.GetSelectedFiles();


  - FtpController's properties
     - I defined properties instead of field that I need.
       Property allows source code is cleaned and developer can make easy coding for simple method like get, set.
      So I think that property is better than field in case not need to performance and special case.

     class FtpController
    {
        //  _ftpAddress  = @"ftp://ftp.novell.com";
        public string FtpAddress { get; set; }
        public string ID { get; private set; }
        public string Password { get; private set; }
        public System.Windows.Forms.ProgressBar _progressBar    = null;
        ...
   }

3. Git

 - GFtp version is v1.3.
   Now I am feeling that version management is difficult without any version management tool.
   So I added GFtp source code to Git.
   Here is Git link.

2017년 3월 8일 수요일

[Development Story] GFtp - #3

GFtp's second update.

1. Update list

 - To add progress bar while translate files.
 - To move between ftp directory using double click.
 - To display more detail ftp file / directory information
 - Disable editing of DataGridView.

2. Demo

 - GFtp v1.2 demo

3. Codes snippets

 - To add progress bar while translate files. 

  First, set a progressbar and whenever translate file increment step using PerformStep() function.
  Next code is to translate files with increment progress bar.

         // Translate files from local to ftp or from ftp to local
        private bool TranslateFiles(string[] files, bool IsUpload)
        {
            // Set a progressbar
            progressBar.Style = ProgressBarStyle.Continuous;
            progressBar.Minimum = 0;
            progressBar.Maximum = files.Length;
            progressBar.Step = 1;
            progressBar.Value = 0;
   

            // connect ftp
            WebClient wc = new WebClient { Proxy = null };
            wc.BaseAddress = _ftpAddress;
            if (_id != "" && _password != "")
            {
                wc.Credentials = new NetworkCredential(_id, _password);
            }

            try
            {
                foreach (string filename in files)
                {
                    string pathName = Path.Combine(_currentDirectory, filename);

                    // increment progress bar
                    progressBar.PerformStep();
                    
                    // upload
                    if (IsUpload)
                    {
                        wc.UploadFile(pathName, filename);
                    }
                    // download
                    else
                    {
                        wc.DownloadFile(filename, pathName);
                    }
                }
            }
            catch
            {
                return false;
            }

            return true;
        }

 - To move between ftp directory using double click.
  First, I made a EventHandler for DoubleClick in both fileGridView and ftpFileGridView.
  Following codes are Add EventHandler to fileGridView and to implement that EventHandelr.
        public Form1()
        {
            InitializeComponent();
   
            // Add a event handler to fileGridView.DoubleClock.
            fileGridView.DoubleClick += FileGridView_DoubleClick;
        }

        // It's called after double clicking on fileGridView. 
        private void FileGridView_DoubleClick(object sender, EventArgs e)
        {
            if (sender != fileGridView)
                return;

            DataGridViewCell cell = fileGridView.CurrentCell;
            // Check clicked cell is file or folder
            bool isFolder = true;
            if (fileGridView.Rows[cell.RowIndex].Cells[2].Value.ToString() == "File")
                isFolder = false;

            // if clicked cell is folder then move current directory to sub directory
            if(isFolder)
            {
                _currentDirectory   = Path.Combine(_currentDirectory, fileGridView.Rows[cell.RowIndex].Cells[0].Value.ToString());
                RefreshFileGridViewOfCurrentDirectory();
            }         
        }

 - To display more detail ftp file / directory information
  To include variety of information for directory and file, I made GridFileInfo class.
  GridFileInfo Inherit IComparable and has CompareTo function for sorting from directory to file.
  I used GridFileInfo for fileGridView and ftpFileGridView. As you know, Ftp file has more detail information than local file. So it may waste memory if you use this class for both.
  But, I thought that can share some function like refresh grid view for file grid view and ftp file grid view. And I thought that it can be increased comfortation for coding.
  Following is GridFileInfo class.
    public class GridFileInfo : IComparable
    {
        public string Name { get; set; }
        public long Size { get; set; }
        public bool IsFolder { get; set; }
       

        public int CompareTo(object obj)
        {
            if(obj is GridFileInfo)
            {
                GridFileInfo tmp = (GridFileInfo)obj;
                if (tmp.IsFolder == IsFolder)
                    return 0;
                else if (tmp.IsFolder == true)
                    return 1;
                else if (IsFolder == true)
                    return -1;
            }
            throw new ArgumentException("Object is not a GridFileInfo");
        }
    }  

 Following is to refresh filegrid view of local directory and show to share FileGridInfo class.
        // Refresh FileTreeView
        // Display all file in the current directory.
        void RefreshFileGridViewOfCurrentDirectory()
        {
            // Get all file list  directory list of my pc;
            DirectoryInfo di = new DirectoryInfo(_currentDirectory);

            // Get all sub directory
            DirectoryInfo[] subDiArray = di.GetDirectories();
           
            // Get all files
            FileInfo[] fiArray = di.GetFiles("*.*");

            GridFileInfo[] gridFileInfos = new GridFileInfo[1 + subDiArray.Length + fiArray.Length];
            int idx = 0;

            // Add super directory
            {
                gridFileInfos[idx] = new GridFileInfo();
                gridFileInfos[idx].Name = "..";
                gridFileInfos[idx].Size = 0;
                gridFileInfos[idx].IsFolder = true;
                idx++;
            }
            
            // Add directory infos
            foreach (DirectoryInfo subDi in subDiArray)
            {
                gridFileInfos[idx] = new GridFileInfo();
                gridFileInfos[idx].Name = subDi.Name;
                gridFileInfos[idx].Size = 0;
                gridFileInfos[idx].IsFolder = true;
                idx++;
            }
         
            // Add file infos
            foreach(FileInfo fi in fiArray)
            {
                gridFileInfos[idx] = new GridFileInfo();
                gridFileInfos[idx].Name = fi.Name;
                gridFileInfos[idx].Size = fi.Length;
                gridFileInfos[idx].IsFolder = false;
                idx++;
            }
            // Display file to grid view
            DisplayFilesToGridView(fileGridView, gridFileInfos);
        }

4. Git

 - I am feeling that uncomfortation to management version and source code.
   So I started manage version and source code using Git.
   From now my source code is shared via GitHub.com.
   My github link is
   https://github.com/gurum77/GFtp

5. Next

 - GFtp version is 1.2. GFtp is getting complex.
   So I will refactoring GFtp. it will be also simple refactoring. Because this project is for just my studying C#.

2017년 3월 6일 월요일

[Development Story] GFtp update plan

v1.2 Update list

 - To add progress bar while translate files.
 - To move between directory (ftp and local) using double click.
 - To display more detail ftp file / directory information
 - Disable editing of DataGridView.

Next Update list

 - To manage version using Git
 - Add icon to DataGridView for files and folders
 - Refactoring source codes


If you have another update items, feel free to reply.
For my study and for your want, I will do best.

2017년 3월 5일 일요일

[Development Story] GFtp - #2

GFtp's first update.
GFtp will be made more pretty, more easy.
So I am going to update GFtp with following list. This update is GFtp v1.1.

1. Update list

 - Image buttons
 - multi select.

2. Searching icons for buttons

 - http://www.flaticon.com/

3. Screenshot

 - GFtp v1.1 is became more pretty than GFtp v1.0.
   But I think that it is too far.

4. Code snippets


- To display file list, I changed a TreeView control to DataGridView. 

   Following codes is to display file list into DataGridView.
   GridFileInfo is a class for file list.
   Function named DisplayFilesToGridView(...) is to display file infoes into DataGridView.
   Caution, to select full columns on DataGridView is set "DataGridView.Columns[col].SortMode = DataGridViewColumnSortMode.NotSortable"

       public class GridFileInfo
       {
           public string Name { get; set; }
           public long Size { get; set; }
       }

        // Display file to grid view
        void DisplayFilesToGridView(DataGridView gridView, GridFileInfo[] fileinfos)
        {
            // initialize file tree view control
            gridView.RowCount = fileinfos.Length;
            gridView.ColumnCount = 2;

            // set column's width
            gridView.Columns[0].Width = 200;
            gridView.Columns[1].Width = 150;

            // set header titles
            gridView.Columns[0].HeaderText = "Name";
            gridView.Columns[1].HeaderText = "Size";

            // Change column's sortmode to NotSortable for DataGridViewSelectionMode.FullColumnSelect
            for (int i = 0; i < gridView.ColumnCount; ++i)
            {
                gridView.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
            }

            gridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            // Set files to grid view
            int rowIndex = 0;
            foreach (GridFileInfo f in fileinfos)
            {
                gridView.Rows[rowIndex].Height = 24;
                gridView.Rows[rowIndex].Cells[0].Value = f?.Name;
                gridView.Rows[rowIndex].Cells[1].Value = f?.Size;

                rowIndex++;
            }
        }

- Get selected file names on DataGridView

  First column contains file name. So you need to get file names on DataGridView, you have to first columns's text.
  Following codes is to get file names on DataGridView.

        // Get file names selected in the grid view
        private string[] GetSelectedFileOfGridView(DataGridView gridView)
        {
            string[] files = new string[gridView.SelectedRows.Count];
            int idx = 0;
            foreach (DataGridViewRow row in gridView.SelectedRows)
            {
                files[idx++] = row.Cells[0].Value.ToString();
            }

            return files;
        }

  GetSelectedFileOfGridView function is used for both current directory DataGridView and Ftp DataGridView.

  - Get file informations on Ftp using FtpWebRequest and FtpWebResponse.

    I changed Request method from WebRequestMethods.Ftp.ListDirectory to WebRequestMethods.Ftp.ListDirectoryDetails.
    WebRequestMethods.Ftp.ListDirectoryDetails allows you get file information more detail like file name, file attribute, file size etc.

     Following codes is to get file detail informations on Ftp.

        // Get all files on ftp root directory
        private GridFileInfo[] GetAllGridFileInfosFromFtp(string ftpAddr, string id, string password)
        {
            Uri ftpUri = new Uri(ftpAddr);
            FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(ftpUri);
            ftpReq.Credentials = new NetworkCredential(id, password);
            ftpReq.Timeout = 30000; // 30 seconds timeout
            ftpReq.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

            FtpWebResponse ftpRes = (FtpWebResponse)ftpReq.GetResponse();

            StreamReader reader = new StreamReader(ftpRes.GetResponseStream(), System.Text.Encoding.Default);

            string str = reader.ReadToEnd();
            string[] fileInfos = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);


            GridFileInfo[] gridFileInfos = new GridFileInfo[fileInfos.Length];
            int idx = 0;
            foreach(string infoString in fileInfos)
            {
                string[] infoArray = infoString.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                gridFileInfos[idx] = new GridFileInfo();
                gridFileInfos[idx].Size = long.Parse(infoArray[4]);
                gridFileInfos[idx].Name = infoArray[8];
                idx++;
            }

            ftpRes.Close();
            return gridFileInfos;
        }

5. Demo


Next time I will update this program to that Ftp Data Grid View is more comfortable.
Source code is shared to anybody.
https://drive.google.com/drive/u/0/folders/0B7BKBqLU8mglMl9UNFZvWmFQUGs
 

2017년 3월 2일 목요일

[Development story] GFtp - #1

I am studying C# since a week ago.
People say "C# is easy to learn." But I don't.
Because I have been programming with only C++ about 20 years.
So It's a little difficult to learn C#.

Now, I am studying C# with "C# 6.0 완벽가이드" and I almost read the book.
So I will try to develop FTP program and that development story will be writen by me.

Today I write first day story.
I am C# beginner. So there will be an inexperienced part.
Welcome any replys, opinions.

1. Program introduce

 - Very very simple FTP program.

2. Functions

 - Translate local file to FTP.

3. Demo




4. Code Snippets

 - Display all files in the current directory.

        // Refresh FileTreeView
        // Display all file in the current directory.
        void RefreshFileTreeViewOfCurrentDirectory()
        {
            // initialize file tree view control
            fileTreeView.Nodes.Clear();

            // Get all file list  directory list of my pc;
            DirectoryInfo di = new DirectoryInfo(_currentDirectory);

            // Get all sub directory
            FileInfo[] fiArray = di.GetFiles("*.*");

            // root node
            TreeNode rootNode = new TreeNode(_currentDirectory);
            rootNode.Text = _currentDirectory;

            foreach(FileInfo f in fiArray)
            {
                TreeNode fileNode = new TreeNode(f.Name);
                rootNode.Nodes.Add(fileNode);
            }
         
            fileTreeView.Nodes.Add(rootNode);

            // expand all file tree view
            fileTreeView.ExpandAll();
        }


 - Select current directory using FolderBrowserDialog

        // When the select director button clicked, select current directory and then refresh file tree view
        private void selectDirectoyButton_Click(object sender, EventArgs e)
        {
            // select directory
            FolderBrowserDialog dlg = new FolderBrowserDialog();
            dlg.SelectedPath = _currentDirectory;
            if (dlg.ShowDialog() == DialogResult.Cancel)
                return;
            _currentDirectory = dlg.SelectedPath;

            RefreshFileTreeViewOfCurrentDirectory();
        }

-  Refresh ftp file list box 

        // Refresh ftp file list box
        void RefreshFtpFileListBox(string ftpAddr, string id, string password)
        {
            string[] fileList = GetAllFileListFromFtp(ftpAddr, id, password);
         
            // display file list into list view
            foreach (string filename in fileList)
            {
                ftpFileListBox.Items.Add(filename);
            }
        }

- Get all files on ftp root directory.

        // Get all files on ftp root directory
        private string[] GetAllFileListFromFtp(string ftpAddr, string id, string password)
        {
            Uri ftpUri = new Uri(ftpAddr);
            FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(ftpUri);
            ftpReq.Credentials = new NetworkCredential(id, password);
            ftpReq.Timeout = 30000;
            ftpReq.Method = WebRequestMethods.Ftp.ListDirectory;

            FtpWebResponse ftpRes = (FtpWebResponse)ftpReq.GetResponse();

            StreamReader reader = new StreamReader(ftpRes.GetResponseStream(), System.Text.Encoding.Default);

            string str = reader.ReadToEnd();
            string[] files = str.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            ftpRes.Close();

            return files;
        }


-  Translate file from local to ftp or from ftp to local (upload or download)

        // Translate files from local to ftp or from ftp to local
        private bool TranslateFiles(string[] files, bool IsUpload)
        {
            // connect ftp
            WebClient wc = new WebClient { Proxy = null };
            wc.BaseAddress = _ftpAddress;
            if (_id != "" && _password != "")
            {
                wc.Credentials = new NetworkCredential(_id, _password);
            }

            try
            {
                foreach (string filename in files)
                {
                    string pathName = Path.Combine(_currentDirectory, filename);
                    // upload
                    if (IsUpload)
                    {
                        wc.UploadFile(pathName, filename);
                    }
                    // download
                    else
                    {
                        wc.DownloadFile(filename, pathName);
                    }
                }
            }
            catch
            {
                return false;
            }

            return true;
        }

5. Result

 I done for one day.
I planed develop very simple ftp. But it's too simple. GFtp can select only one file. And It has no image, so it's not pretty.
So I decided to do version up.
Next time, I will add some functions for more easy and more pretty GFtp.

This is GFtp ver1.0 and I share source file by link.

There are all source in the following link.
https://drive.google.com/drive/folders/0B7BKBqLU8mglMl9UNFZvWmFQUGs?usp=sharing

GFtp is developed using Visual Studio 2015.