Windows Script Host Object Model Folders and Files

krikikriki Member, Moderator Posts: 9,112
edited 2012-03-14 in NAV Tips & Tricks
For once I am not resolving a problem, but posting one.
I need to scan a subdirectory for files and subdirectories. In general virtual table "File" works, but now the directory-structure is so deep that the filter on field "Path" generates an error (value in the filter .... is too long for the field type).
So I am trying Automation.
These are the variables I declared:
Lint	Integer		
LautFileSystemObject	:'Windows Script Host Object Model'.FileSystemObject	
LautFolder	:'Windows Script Host Object Model'.Folder	
LautFolder2	:'Windows Script Host Object Model'.Folder	
LautFolders	:'Windows Script Host Object Model'.Folders

and this is the code:
CREATE(LautFileSystemObject);
LautFolder :=  LautFileSystemObject.GetFolder('c:\temp');
LautFolders := LautFolder.SubFolders();

FOR Lint := 1 TO LautFolders.Count() DO BEGIN
  LautFolder2 := LautFolders.Item(Lint); // This goes wrong
END;

CLEAR(LautFileSystemObject);
When I run this peace of code I get the error:"An exception occurred from an external component. The component did not provide the exception description".
What am I doning wrong?
Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


Answers

  • kinekine Member Posts: 12,562
    From documentation of the Subfolders class:
    [VBScript]
    Function ItemDemo
       Dim d   ' Create some variables.
       Set d = CreateObject("Scripting.Dictionary")
       d.Add "a", "Athens"   ' Add some keys and items.
       d.Add "b", "Belgrade"
       d.Add "c", "Cairo"
       ItemDemo = d.Item("c")   ' Get the item.
    End Function
    

    It seems, that the index is not no. but may be some other key...
    Kamil Sacek
    MVP - Dynamics NAV
    My BLOG
    NAVERTICA a.s.
  • krikikriki Member, Moderator Posts: 9,112
    I also found this documentation, but I fail to see how I can use it to solve my problem.
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • kinekine Member Posts: 12,562
    I am afraid that without iterating functions you will be not able to do this in Navision in this way... (or you need to search for keys which are associated as default with the folders)
    Kamil Sacek
    MVP - Dynamics NAV
    My BLOG
    NAVERTICA a.s.
  • CodeGeniusCodeGenius Member Posts: 40
    Hi Kine,

    I suppose your trying to get a list of folders using Navision.

    If I were you I would not use Windows Script Host Object Model. Navision has the table file that you can use to walk through Files & Folders.

    Here's an example:
    Variables:
    Name	DataType	Subtype	Length
    FileRec	Record	File	
    
    Code:
    FileRec.SETRANGE(Path, 'C:\Temp');
    FileRec.SETRANGE("Is a file", False);           // TRUE for files, FALSE for folders...
    IF FileRec.FIND('-') THEN
      REPEAT
        if not (FileRec.Name IN ['.', '..']) then   // Skip current and parent folder...
          MESSAGE(FileRec.Name);
      UNTIL FileRec.NEXT = 0;
    

    I think this will be a easier way to accomplish the same. Hope this is some help! :wink:
  • krikikriki Member, Moderator Posts: 9,112
    Hi CodeGenius,

    I think you are suffering the Friday-afternoon-disease. :wink:

    I know very well this table. Problem is that it doesn't work if the path goes to deep. So I am forced to find another solution.
    I tried that automation, but I got stuck on retrieving all the subdirs and files in a subdir.
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • CodeGeniusCodeGenius Member Posts: 40
    kriki wrote:
    I think you are suffering the Friday-afternoon-disease. :wink:

    No Friday-afternoon-disease, just looking for an alternative for your problem. Collection types in WSH do not work very well with Navision. Why? I cannot tell you, I didn't make the IFolderCollection interface :wink:

    I was just trying to be helpful... :)
  • krikikriki Member, Moderator Posts: 9,112
    CodeGenius wrote:
    kriki wrote:
    I think you are suffering the Friday-afternoon-disease. :wink:

    No Friday-afternoon-disease, just looking for an alternative for your problem. Collection types in WSH do not work very well with Navision. Why? I cannot tell you, I didn't make the IFolderCollection interface :wink:

    I was just trying to be helpful... :)
    Thanx for the help.
    But you should read the problem better. :wink: I wrote in it that I had problems with the File-table.
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • azwierzchowskiazwierzchowski Member Posts: 15
    In folders collection folders are indexed by name.
    Use Microsoft Script Control:

    Variables:
    scr Automation 'Microsoft Script Control 1.0'.ScriptControl
    txtCode Text 1024
    RetVal Variant
    count Integer
    i Integer
    txtCR Text 30
    FolderName Text 1024

    And code:

    txtCR := ' '; txtCR[1] := 13;
    create(scr);
    scr.Language := 'VBScript';

    //declare global collection
    txtCode :=
    'dim Folders' + txtCR;
    scr.AddCode(txtCode);

    //find folders and copy them to collection
    txtCode :=
    'sub LoadFolderList(folderspec)' + txtCR +
    ' Dim fso, f, f1, s, sf' + txtCR +
    '' + txtCR +
    ' set Folders = CreateObject("Scripting.Dictionary")' + txtCR +
    '' + txtCR +
    ' Set fso = CreateObject("Scripting.FileSystemObject")' + txtCR +
    ' Set f = fso.GetFolder(folderspec)' + txtCR +
    ' Set sf = f.SubFolders' + txtCR +
    ' For Each f1 in sf' + txtCR +
    ' Folders.Add (Folders.Count+1), f1' + txtCR +
    ' Next' + txtCR +
    'End sub' + txtCR;
    scr.AddCode(txtCode);

    txtCode :=
    'function GetCount' + txtCR +
    ' GetCount = Folders.Count' + txtCR +
    'end function' + txtCR;
    scr.AddCode(txtCode);

    txtCode :=
    'function GetFolder(i)' + txtCR +
    ' getFolder = Folders(i)' + txtCR +
    'end function' + txtCR;
    scr.AddCode(txtCode);

    scr.ExecuteStatement('LoadFolderList "C:\temp\"');

    RetVal := scr.Eval('GetCount');
    count := RetVal;

    for i:=1 to count do begin
    RetVal := scr.Eval('GetFolder(' + format(i) + ')');
    FolderName := RetVal;
    message(FolderName);
    end;

    CLEAR(scr);
  • kinekine Member Posts: 12,562
    :shock: indexing something I want to know by the value I want to know... #-o

    I know that in VB no problem... but... ](*,)
    Kamil Sacek
    MVP - Dynamics NAV
    My BLOG
    NAVERTICA a.s.
  • jreynoldsjreynolds Member Posts: 175
    azwierzchowski,

    This is a very clever technique. Thanks for sharing it.
  • wakestarwakestar Member Posts: 207
    In folders collection folders are indexed by name.
    Use Microsoft Script Control:
    Variables:
    scr Automation 'Microsoft Script Control 1.0'.ScriptControl
    txtCode Text 1024
    RetVal Variant
    ...

    nice!
    I used to write and run *.vbs files dynamically at runtime, but your code is in navision - that's cool 8)
  • azwierzchowskiazwierzchowski Member Posts: 15
    Another solution, now almost everything is done in Navision.

    Script control allows to add Automation controls from your code, so there is another solution. This time VBScript is used only for copying folders objects from collection indexed by folder name to collection indexed by integer value.

    Variables from oryginal code:

    LautFileSystemObject Automation 'Windows Script Host Object Model'.FileSystemObject
    LautFolder Automation 'Windows Script Host Object Model'.Folder
    LautFolder2 Automation 'Windows Script Host Object Model'.Folder
    LautFolders Automation 'Windows Script Host Object Model'.Folders
    LInt Integer

    My new variables:
    FoldersCol Automation 'Microsoft Scripting Runtime'.Dictionary
    txtCode Text 250
    txtCR Text 30
    scr Automation 'Microsoft Script Control 1.0'.ScriptControl

    Code:

    CREATE(LautFileSystemObject);
    LautFolder := LautFileSystemObject.GetFolder('c:\temp');
    LautFolders := LautFolder.SubFolders();
    create(FoldersCol);

    create(scr);
    scr.Language := 'VBScript';
    //variable LautFolders is visible in script as FoldersByName
    scr.AddObject('FoldersByName', LautFolders);
    //variable FoldersCol is visible in script as FoldersById
    scr.AddObject('FoldersById', FoldersCol);

    //copy objects using VBScript
    txtCR := ' '; txtCR[1] := 13;
    txtCode :=
    'dim f1' + txtCR +
    'For Each f1 in FoldersByName' + txtCR +
    ' FoldersById.Add (FoldersById.Count+1), f1' + txtCR +
    'Next' + txtCR;
    scr.ExecuteStatement(txtCode);

    clear(scr);

    //now we can use collection of folders in Navision
    FOR Lint := 1 TO FoldersCol.Count() DO BEGIN
    LautFolder2 := FoldersCol.Item(Lint);
    message(LautFolder2.Name);
    END;
  • krikikriki Member, Moderator Posts: 9,112
    Thanx azwierzchowski. :D:D:D:D
    It works! (I have finally time to check it out. And I am still trying to understand it)
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • janpieterjanpieter Member Posts: 298
    Hey thanks for the vbscript example that is cool. I tried it once but didn't get any further because i thought navision was unable to handle some parameters; but so it seems to be possible =D>
    In a world without Borders or Fences, who needs Windows and Gates?
  • janpieterjanpieter Member Posts: 298
    Its a shame, vbscripting does not allow API calls :cry: ](*,)
    In a world without Borders or Fences, who needs Windows and Gates?
  • Marije_BrummelMarije_Brummel Member, Moderators Design Patterns Posts: 4,262
    This is a great solution. =D>

    I've used it today and added the files to it.

    CREATE(FileSystemObject); 
    Folder := FileSystemObject.GetFolder('C:\Edi');
    Folders := Folder.SubFolders(); 
    CREATE(DictionaryFolders);
    CREATE(DictionaryFiles);
    
    CREATE(ScriptControl);
    ScriptControl.Language := 'VBScript';
    
    ScriptControl.AddObject('FoldersByName', Folders);
    ScriptControl.AddObject('FoldersById', DictionaryFolders);
    
    CrLf := ' ';
    CrLf[1] := 13;
    Script := 'dim f1' + CrLf +
              'For Each f1 in FoldersByName' + CrLf +
              ' FoldersById.Add (FoldersById.Count + 1), f1' + CrLf +
              'Next' + CrLf;
    
    ScriptControl.ExecuteStatement(Script);
    
    CLEAR(ScriptControl);
    
    FOR i := 1 TO DictionaryFolders.Count() DO BEGIN
      Folder2 := DictionaryFolders.Item(i);
      
      Files := Folder2.Files;
      
      CREATE(ScriptControl);
      ScriptControl.Language := 'VBScript';
    
      ScriptControl.AddObject('FilesByName', Files);
      ScriptControl.AddObject('FilesById', DictionaryFiles);
      CrLf := ' ';
      CrLf[1] := 13;
      Script := 'dim f1' + CrLf +
                'For Each f1 in FilesByName' + CrLf +
                ' FilesById.Add (FilesById.Count + 1), f1' + CrLf +
                'Next' + CrLf;
    
      ScriptControl.ExecuteStatement(Script);
    
      CLEAR(ScriptControl);
    
      MESSAGE(Folder2.Name);
      MESSAGE(FORMAT(Files.Count));
      
      FOR n := 1 TO DictionaryFiles.Count DO BEGIN
        Fle := DictionaryFiles.Item(n);
        MESSAGE(Fle.Name);
      END;
    END;
    

    Variables:
    Name	DataType	Subtype	Length
    FileSystemObject	Automation	'Windows Script Host Object Model'.FileSystemObject	
    Folder	Automation	'Windows Script Host Object Model'.Folder	
    Folder2	Automation	'Windows Script Host Object Model'.Folder	
    Folders	Automation	'Windows Script Host Object Model'.Folders	
    Fle	Automation	'Windows Script Host Object Model'.File	
    Files	Automation	'Windows Script Host Object Model'.Files	
    DictionaryFolders	Automation	'Microsoft Scripting Runtime'.Dictionary	
    DictionaryFiles	Automation	'Microsoft Scripting Runtime'.Dictionary	
    ScriptControl	Automation	'Microsoft Script Control 1.0'.ScriptControl	
    Script	Text		250
    CrLf	Text		2
    i	Integer		
    n	Integer
    

    I'll send it to the downloads also. :mrgreen:
  • krikikriki Member, Moderator Posts: 9,112
    I'll send it to the downloads also. :mrgreen:
    I think it might already be somewhere. This is code I already used and I found it on Mibuso.
    But I am not sure where it is.




    Found it : It was a reply to a problem I had.... :oops: I need to install some more memory in my head! :mrgreen:
    This is the link: http://www.mibuso.com/forum/viewtopic.php?t=7855

    Maybe you can post some code that is usable for all kind of problems in the tips&tricks
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • SaroSaro Member Posts: 58
    krikri
    i had the same problem as well it turned out that i was getting the message for trying to "get" a non existing folder.

    i hope this solves ur problem
    Saro
  • krikikriki Member, Moderator Posts: 9,112
    [Topic moved from Navision forum to Navision Tips & Tricks forum]
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • KowaKowa Member Posts: 923
    I tried this out today, works fine for the classic client, but the same object when run with the RTC shows only a error message that the assembly dll file cannot be compiled due to invalid parameters.
    Kai Kowalewski
  • Troubles_In_ParadiseTroubles_In_Paradise Member Posts: 588
    Kowa wrote:
    I tried this out today, works fine for the classic client, but the same object when run with the RTC shows only a error message that the assembly dll file cannot be compiled due to invalid parameters.

    I have the same problem... :(
    ~Rik~
    It works as expected... More or Less...
  • krikikriki Member, Moderator Posts: 9,112
    Just a wild guess:Try to experiment with the parameters of the CREATE-command. With the introduction of RTC, it got some boolean parameters.
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • Troubles_In_ParadiseTroubles_In_Paradise Member Posts: 588
    kriki wrote:
    Just a wild guess:Try to experiment with the parameters of the CREATE-command. With the introduction of RTC, it got some boolean parameters.
    Hi kriki, unfortunately I've already tried setting parameters for creating on client and for new server but no luck...
    ~Rik~
    It works as expected... More or Less...
  • krikikriki Member, Moderator Posts: 9,112
    If you are using 2009R2, search for a .NET alternative.
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • Troubles_In_ParadiseTroubles_In_Paradise Member Posts: 588
    kriki wrote:
    If you are using 2009R2, search for a .NET alternative.
    Thx for suggestion... I'll let you know If I find something.
    ~Rik~
    It works as expected... More or Less...
  • Troubles_In_ParadiseTroubles_In_Paradise Member Posts: 588
    kriki wrote:
    If you are using 2009R2, search for a .NET alternative.
    I found this link very usefull, it solved my problems:
    http://blogs.msdn.com/b/nav/archive/201 ... 09-r2.aspx
    ~Rik~
    It works as expected... More or Less...
  • nayenaye Member Posts: 4
    DataType	Name	Subtype	Length
    Automation	MS_Shell	'Microsoft Shell Controls And Automation'.Shell	
    Automation	MS_Folder	'Microsoft Shell Controls And Automation'.Folder3	
    Automation	MS_FolderItems	'Microsoft Shell Controls And Automation'.FolderItems3	
    Automation	MS_FolderItem	'Microsoft Shell Controls And Automation'.FolderItem
    
    CREATE(MS_Shell, TRUE);
    MS_Folder := MS_Shell.BrowseForFolder(0, 'Select The Folder', 0);
    IF NOT ISCLEAR( MS_Folder ) THEN
      SelectedFolder := FORMAT(MS_Folder.Self.Path);
    
    IF SelectedFolder = '' THEN EXIT;
    
    MS_FolderItems := MS_Folder.Items;
    
    IF NOT ISCLEAR( MS_FolderItems ) THEN
      FOR I := 1 TO MS_FolderItems.Count DO BEGIN
        MS_FolderItem := MS_FolderItems.Item(I);
        IF NOT ISCLEAR( MS_FolderItem ) THEN BEGIN
          MESSAGE(MS_FolderItem.Path);
          MESSAGE(MS_FolderItem.Name);
          MESSAGE(MS_FolderItem.Type);
          MESSAGE('%1', MS_FolderItem.IsFolder);
          CLEAR( MS_FolderItem );
        END;
      END;
    
    CLEAR( MS_FolderItem );
    CLEAR( MS_FolderItems );
    CLEAR( MS_Folder );
    CLEAR( MS_Shell );	
    
Sign In or Register to comment.