trashy

Recursive file search

27 posts in this topic

#1 ·  Posted

Using DISM driver export function gives some long and really odd names to folders.

Example: C:\driver\nv_dispi.inf_x86_neutral_86a60910630f5129\nv_dispi.inf

Driver folder contains about 12 sub folders with driver files.

 I need to do a recursive search of all the sub folders read the driver.inf file and move all files to new folder.

The new folder structure would be based on Class name and provider name returned from driver.inf.

Example C:\Driver\Display\Nvidia.

Never used arrays before but  _FileListToArrayRec seemed like a simple solution for the file search.

_ArrayDisplay list all .inf file as expected but _FileWriteFromArray gives me a blank text file.

I have the rest of the process worked out but I need .inf file path and name.

Tried _ArrayExtract but got nothing also.

 

#include <Array.au3>
#include <File.au3>

$filepath = "C:\driver"

$search = _FileListToArrayRec ($filepath & "", "*.inf", 1, -1, 1)
 _ArrayDisplay($search, ".inf Files")

$atext = @ScriptDir & "\Examples.txt"
_FileWriteFromArray($atext, $search, 1);<<<< nothing returned blank txt file

Local $aExtract = _ArrayExtract($search, 0, 3, 0, 0)
_ArrayDisplay($aExtract, "Row 0-3 column 0");<<<< array display never appears

Using Autoit I have created an awesome GUI for DISM called Easy_DISM 12 tabs and growing.

Have a look http://theoven.org/index.php?topic=933.0

I would like to post Easy_DISM here on the AutoIt forum but where.

I want more exposure see if I can give the other DISM GUIs a run for their money.

I also need some help Easy_DISM works great and seems stable but would like an expert opinion.

When I started on this a couple years ago I knew nothing about AutoIt.

Help Me!

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

What is the error and return code from the _FileWriteFromArray() udf?
Why not simply loop through the created Array with a For...Next loop and test each  entry in the array for the appropriate filename?
That should return the full path for the file which you can use to extract the source path.

Jos

Edited by Jos

Visit the SciTE4AutoIt3 Download page for the latest versions  - Beta files                                How to post scriptsource        Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#3 ·  Posted

Can you try something like this to create a CSV file with filepath, first folder and Inf class name?  You could also use the array to move files etc...

#include <Array.au3>
#include <File.au3>

Global $hFilePath = 'C:\Drivers'

Global $aSearch = _FileListToArrayRec ($hFilePath, "*.inf", 1, 1, 1, 1)

Global $aArray[UBound($aSearch)][3]
For $x = 1 To $aSearch[0]
    $aArray[$x][0] = $hFilePath & '\' & $aSearch[$x]
    $aArray[$x][1] = StringLeft($aSearch[$x], StringInStr($aSearch[$x], '\') - 1)
    $aArray[$x][2] = IniRead($aSearch[$x], 'Version', 'Class', 'Misc')
Next
$aArray[0][0] = UBound($aArray) - 1
_ArrayDisplay($aArray, ".inf Files")

Global $sFileText = @ScriptDir & "\Examples.csv"
Global $hFileText = FileOpen($sFileText, 2)
If $hFileText = -1 Then
    ConsoleWrite('Error opening: ' & $sFileText & @CRLF)
    Exit
EndIf

_FileWriteFromArray($hFileText, $aArray, 1, Default, ',')

FileClose($hFileText)

 

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Man do I feel stupid!
@jos no errors cause it was all me.

@Subz it was tinkering with your example I realized array display the button I clicked

says Exit Script not EXIT. Hit esc or x and close it and I get exactly what supposed to.

I have no background writing code can't type, copy paste mostly, been working with AutoIt

for couple years and feel dumber than the day I started.

This is all I needed works perfect

#include <Array.au3>
#include <File.au3>

$filepath = "C:\driver"

$search = _FileListToArrayRec ($filepath & "", "*.inf", $FLTAR_FILES, -1, $FLTAR_SORT)
$atext = @ScriptDir & "\Examples.txt"
_FileWriteFromArray($atext, $search, 1)

 

Edited by trashy

Share this post


Link to post
Share on other sites

#5 ·  Posted

:D Glad you got it sorted, the reason I suggested using the 2D Array was so that you can create your folders from the Array, without having to create them manually.  You can also copy the files associated by viewing the SourceDiskFiles Section in each .inf file as these are the only files required for the driver.

If you need help with that I'm happy to assist.

Share this post


Link to post
Share on other sites

#6 ·  Posted

Subz I may take you up on that with what I've got getting close but also getting in over my head.

 

Share this post


Link to post
Share on other sites

#7 ·  Posted

Can you give the following a try:

#include <Array.au3>
#include <File.au3>

Global $hSRC_FILEPATH = 'C:\Driver', $hDST_FILEPATH = 'C:\Update', $aSRC_DISKFILE

Global $aSRC_FILEPATH = _FileListToArrayRec ($hSRC_FILEPATH, "*.inf", 1, 1, 1, 1)

Global $aINF_FILEINFO[UBound($aSRC_FILEPATH)][4]
For $x = 1 To $aSRC_FILEPATH[0]
    ;~ .inf Source File Path
    $aINF_FILEINFO[$x][0] = $hSRC_FILEPATH & '\' & $aSRC_FILEPATH[$x]
    ;~ .inf Source Folder Path
    $aINF_FILEINFO[$x][1] = $hSRC_FILEPATH & '\' & StringLeft($aSRC_FILEPATH[$x], StringInStr($aSRC_FILEPATH[$x], '\', 0, -1) - 1)
    ;~ .inf Provider name
    $aINF_FILEINFO[$x][2] = StringReplace(IniRead($aSRC_FILEPATH[$x], 'Version', 'Provider', 'Unknown_Provider'), '"', '')
    ;~ .inf Class name
    $aINF_FILEINFO[$x][3] = IniRead($aSRC_FILEPATH[$x], 'Version', 'Class', 'Misc')
Next
$aINF_FILEINFO[0][0] = UBound($aINF_FILEINFO) - 1

For $i = 1 To $aINF_FILEINFO[0][0]
    ;~ .inf Array of Driver Source Disk Files
    $aSRC_DISKFILE = IniReadSection($aINF_FILEINFO[$i][0], 'SourceDisksFiles')
        If @error Then ContinueLoop
    For $j = 1 To $aSRC_DISKFILE[0][0]
        ;~ Copy Source Disk Files to Destinaton Folder
        If FileExists($aINF_FILEINFO[$i][1] & '\' & $aSRC_DISKFILE[$j][0]) Then FileCopy($aINF_FILEINFO[$i][1] & '\' & $aSRC_DISKFILE[$j][0], $hDST_FILEPATH & '\' & $aINF_FILEINFO[$i][2] & '\' & $aINF_FILEINFO[$i][3] & '\', 9)
    Next
    ;~ Copy .inf File to Destination Folder
    FileCopy($aINF_FILEINFO[$i][0], $hDST_FILEPATH & '\' & $aINF_FILEINFO[$i][2] & '\' & $aINF_FILEINFO[$i][3] & '\', 9)
Next
_ArrayDisplay($aINF_FILEINFO, ".inf Files")

 

Share this post


Link to post
Share on other sites

#8 ·  Posted

Subz you accomplished more than I did in half the lines of code

ArrayDisplay colum 2 and 3 List everything Unknown Provider and Misc.

All driver files moved to same folder C:\Update\Unknown_Provider\Misc.

I had to strip the white spaces to read Class name.

#include <String.au3>
#include <File.au3>
#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>

$driverpath = "C:\driver"
$atext = @ScriptDir & "\DriverPaths.txt"
$btext = @ScriptDir & "\DriverInfo.txt"

$arraysearch = _FileListToArrayRec($driverpath & "", "*.inf", $FLTAR_FILES, -1, $FLTAR_SORT, $FLTAR_FULLPATH)
_ArrayDisplay($arraysearch, ".inf Files")

_FileWriteFromArray($atext, $arraysearch, 1)

$aFileOpen = FileOpen($atext, $FO_READ)
$areadline = FileReadLine($aFileOpen)
MsgBox($MB_SYSTEMMODAL, "", $areadline)

$aread = FileRead($areadline)
$entry1 = _StringBetween($aread, "[VERSION]", "[");<<<Read the string Between Version and whatever the next header might be
MsgBox($MB_SYSTEMMODAL, "Driver Info", "[Version]" & $entry1[0])
FileDelete($btext)

$fwrite = FileWrite($btext, $entry1[0])
$sFileRead = FileRead($btext)
$sString = StringReplace($sFileRead, " ", "");<<<<Strip the white spaces from each line
MsgBox($MB_SYSTEMMODAL, "Driver Info", "[Version]" & $sString)
FileDelete($btext)

$gwrite = FileWrite($btext, $sString)
$asearch = "Class="

$sFilePath = $btext
$s = FileRead($sFilePath)
$iCharPos = StringInStr($s, $asearch)
If $iCharPos Then
    $good = StringLeft($s, $iCharPos)
    $LineNumber = StringLen(StringAddCR($good)) - $iCharPos + 1
    $bFileOpen = FileOpen($sFilePath, $FO_READ)
    If $bFileOpen = -1 Then
        MsgBox($MB_SYSTEMMODAL, "", "An error occurred when reading the file.")
    EndIf
    $sFileRead = FileReadLine($bFileOpen, $LineNumber)
    FileClose($bFileOpen)

    $it1 = StringRegExpReplace($sFileRead, "(Class=*)", "");<<<<Strip Class= from the string leavng class name Display or whatever

    FileDelete($btext)
    MsgBox($MB_SYSTEMMODAL, "", $it1)
    $hwrite = FileWrite($btext, $it1)
EndIf

I would have to run everything through a loop or something to get more than just the first driver

and still working on moving files to new folder structure.

C:\newdriver\classname\originalfolder\driverfiles (This would be ideal).

First time I've dealt with an array looks like the way to go.

Got to go to work in couple hours and won't be back for awhile.

Thanks

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Puzzled with your results, I ran "Dism /Online /Export-Driver /Destination:D:\Drivers" and used the script in Post#7 and got the correct class names and providers, I have updated the script and now get the results attached.  I put in a splash screen during the copying and everything appears to be copying into the correct folders.

#include <Array.au3>
#include <File.au3>

Global $hSRC_FILEPATH = 'D:\Drivers', $hDST_FILEPATH = 'D:\NewDriver', $aSRC_DISKFILE

Global $aSRC_FILEPATH = _FileListToArrayRec ($hSRC_FILEPATH, "*.inf", 1, 1, 1, 1)

Global $aINF_FILEINFO[UBound($aSRC_FILEPATH)][5]

For $i = 1 To $aSRC_FILEPATH[0]
    ;~ .inf Source File Path
    $aINF_FILEINFO[$i][0] = $hSRC_FILEPATH & '\' & $aSRC_FILEPATH[$i]
    ;~ .inf Class name
    $aINF_FILEINFO[$i][1] = _FNC_INFCLEAN(IniRead($aINF_FILEINFO[$i][0], 'Version', 'Class', 'Misc'))
    ;~ .inf Provider name
    $aINF_FILEINFO[$i][2] = _FNC_INFCLEAN(IniRead($aINF_FILEINFO[$i][0], 'Version', 'Provider', 'Unknown_Provider'))
    ;~ .inf Source Folder Path
    $aINF_FILEINFO[$i][3] = $hSRC_FILEPATH & '\' & StringLeft($aSRC_FILEPATH[$i], StringInStr($aSRC_FILEPATH[$i], '\', 0, -1) - 1)
    ;~ .inf Destination Folder Path
    $aINF_FILEINFO[$i][4] = $hDST_FILEPATH & '\' & $aINF_FILEINFO[$i][1] & '\' & StringLeft($aSRC_FILEPATH[$i], StringInStr($aSRC_FILEPATH[$i], '\', 0, -1) - 1)
Next
_ArraySort($aINF_FILEINFO, 0, 1, 0, 1)
$aINF_FILEINFO[0][0] = UBound($aINF_FILEINFO) - 1
_ArrayDisplay($aINF_FILEINFO, '', '', 0, Default, '.inf File Path|.inf Class Name|.inf Provider Name|.inf Source Folder Path|.inf Destination Folder Path')

SplashTextOn('Driver File Copy', 'File Copy', 700, 100, -1, -1, 4, 'Trebuchet MS')
For $i = 2 To $aINF_FILEINFO[0][0]
    ;~ .inf Array of Driver Source Disk Files
    $aSRC_DISKFILE = IniReadSection($aINF_FILEINFO[$i][0], 'SourceDisksFiles')
        If @error Then ContinueLoop
    For $j = 1 To $aSRC_DISKFILE[0][0]
        ;~ Copy Source Disk Files to Destinaton Folder
        If FileExists($aINF_FILEINFO[$i][3] & '\' & $aSRC_DISKFILE[$j][0]) Then
            ControlSetText('Driver File Copy', '', 'Static1', 'Copy: ' & $aINF_FILEINFO[$i][3] & '\' & $aSRC_DISKFILE[$j][0] & @CRLF & @CRLF & 'To: ' & $aINF_FILEINFO[$i][4] & '\' & $aSRC_DISKFILE[$j][0])
            FileCopy($aINF_FILEINFO[$i][3] & '\' & $aSRC_DISKFILE[$j][0], $aINF_FILEINFO[$i][4] & '\' & $aSRC_DISKFILE[$j][0], 9)
        EndIf
    Next
    ;~ Copy .inf File to Destination Folder
    ControlSetText('Driver File Copy', '', 'Static1', 'Copy: ' & $aINF_FILEINFO[$i][0] & @CRLF & @CRLF & 'To: ' & $aINF_FILEINFO[$i][3], $aINF_FILEINFO[$i][4])
    FileCopy($aINF_FILEINFO[$i][0], StringReplace($aINF_FILEINFO[$i][0], $aINF_FILEINFO[$i][3], $aINF_FILEINFO[$i][4]), 9)
Next
SplashOff()
_ArrayDisplay($aINF_FILEINFO, '', '', 0, Default, '.inf File Path|.inf Class Name|.inf Provider Name|.inf Source Folder Path|.inf Destination Folder Path')

Func _FNC_INFCLEAN($sINF_CLASSNAME)
    $sINF_CLASSNAME = StringStripWS($sINF_CLASSNAME, 7)
    $sINF_CLASSNAME = StringReplace($sINF_CLASSNAME, '"', '')
    $sINF_CLASSNAME = StringReplace($sINF_CLASSNAME, '%', '')
    Return $sINF_CLASSNAME
EndFunc

 

Drivers.png

Edited by Subz

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Just tested your new script drivers copied to NewDriver\Misc\blahblah

I see you're using iniread I tested and reads the version section and not affected by white spaces.

Wish I found iniread sooner perfect for reading driver inf files.

I'm running Windows 7 on an old dinosaur dell 4gb ram limit and autoit up to date.

Tested on 32bit and 64bit with same results. Found a couple driver inf files that had no structure

everything run together in 2 or 3 lines. Deleted everything from source folder except 1 Nvidia driver, same results.

I'm baffled!

Couple inches of snow and nobody wants to show up for work so I gotta pull another shift.

 

Drivers_01.jpg

Edited by trashy

Share this post


Link to post
Share on other sites

#11 ·  Posted

Subz by the way have you looked at Easy_DISM. Link to download page in m first post.

Would really like your opinion. Need to find a home for it here somewhere.

 

 

Share this post


Link to post
Share on other sites

#12 ·  Posted

Can you edit one of the drivers in notepad and tell me the results of "Version" for "class" and "provider"?  If its returning "Misc" or "Unknown Provider" then it means that the inf doesn't include:

[Version]
Class = ....
Provider = ....

Can you confirm?

7 hours ago, trashy said:

Subz by the way have you looked at Easy_DISM. Link to download page in m first post.

I have it looks good, I wrote my own a while ago but not as clean as yours :)  Noticed that I get an error message regarding Dism and ImageX at the beginning, I would recommend checking for Windows Assessment Kit install and then point Dism to that folder, ImageX has been depreciated in Windows 10 so maybe detect the OS and disable that for @OSBuild.  I tend to use my tool for removing provisioned apps that I don't want as well as configuring the "Default User" profile, when I get a chance I'm going to try and write a template of sorts for each of the versions, for example Windows 10 1607 (Enterprise), 2016 (LTSB), so that I can apply these templates to any future updates.  See if you can post it to "Example" Scripts on the forum and if not post it here and ask one of the mods to move it to Examples.

Share this post


Link to post
Share on other sites

#13 ·  Posted

 

2 hours ago, Subz said:

Can you edit one of the drivers in notepad and tell me the results of "Version" for "class" and "provider"?  If its returning "Misc" or "Unknown Provider" then it means that the inf doesn't include:

That was the first thing I did. Found one that that was one long string 2 lines of text I would expect it to go to Misc.

The rest are all similar to this below.

[Version]
Signature   = "$Windows NT$"
Provider    = %NVIDIA%
ClassGUID   = {4D36E968-E325-11CE-BFC1-08002BE10318}
Class       = Display
DriverVer   = 10/02/2012, 9.18.13.0697
CatalogFile = NV_DISP.CAT

I intentionally used @ScriptDir so if I'm running windows 7 I can use dism for 8.1 or 10. I'm using Dism 10 doesn't matter what version OS or PE running can work on an version Windows Image. Throw Easy_DISM in folder where DISM is and make a desktop shortcut. The only thing I used Imagex for was to edit name and description of an Image.

The only real restriction is there can be no spaces in path to folder containing Easy_DISM.

 

 

Share this post


Link to post
Share on other sites

#14 ·  Posted

Just tried on Windows 7 and found that it doesn't recognize the partial file path when reading the ini like in Windows 10.  I have now changed the script in Post#9 and is now working in Windows 7 can you please try that script again?

 

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

That's it works perfect

I see the changes line 14 and 16 ($aINF_FILEINFO[$i][0]

Just to help me understand

Edit: You said partial file path so still compatible with windows 10?

Edited by trashy

Share this post


Link to post
Share on other sites

#16 ·  Posted

Previously lines 14 and 16 were using: "IniRead($aSRC_FILEPATH[$i], ..." which resolved to something like <Driver Folder>\Filename.inf
Example: IniRead('prnms001.inf_amd64_10bd6dee10a7dfd0\prnms001.Inf',...

In Windows 10 it recognized the partial folder path, which allowed IniRead to return the class and provider names correctly, in Windows 7 it didn't.

So now I have changed it to "IniRead( $aINF_FILEINFO[$i][0],..." which resolves to <Source Folder Path>\<Driver Folder>\Filename.inf
Example: IniRead('C:\Drivers\prnms001.inf_amd64_10bd6dee10a7dfd0\prnms001.Inf',...

Hope that makes sense.

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

I understood that was just curious if that was only change you made. I see now it is.

I want to give you full credit couldn't have done it without your help. You showed me the power of an array!  I Would like to Know what other functions I could add to Easy_DISM for you. Put it to the test and tell me what you think.

Thank You

Edited by trashy

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

Subz I made a few minor changes and am ready to add to Easy_DISM.

Destination folder same as source. Inf search 1 sub folder in depth. Added provider name to destination folder structure. Deleted Array Display and Splash Text. Added a loop to delete original driver folders. Again Thank You so much for your help.

#include <Array.au3>
#include <File.au3>

Global $hSRC_FILEPATH = 'C:\Driver', $hDST_FILEPATH = 'C:\Driver', $aSRC_DISKFILE
Global $aSRC_FILEPATH = _FileListToArrayRec ($hSRC_FILEPATH, "*.inf", 1, -1, 1, 1)
Global $aINF_FILEINFO[UBound($aSRC_FILEPATH)][5]

For $i = 1 To $aSRC_FILEPATH[0]
    $aINF_FILEINFO[$i][0] = $hSRC_FILEPATH & '\' & $aSRC_FILEPATH[$i]
    $aINF_FILEINFO[$i][1] = _FNC_INFCLEAN(IniRead($aINF_FILEINFO[$i][0], 'Version', 'Class', 'Misc'))
    $aINF_FILEINFO[$i][2] = _FNC_INFCLEAN(IniRead($aINF_FILEINFO[$i][0], 'Version', 'Provider', 'Unknown_Provider'))
    $aINF_FILEINFO[$i][3] = $hSRC_FILEPATH & '\' & StringLeft($aSRC_FILEPATH[$i], StringInStr($aSRC_FILEPATH[$i], '\', 0, -1) - 1)
    $aINF_FILEINFO[$i][4] = $hDST_FILEPATH & '\' & $aINF_FILEINFO[$i][1] & '\' & StringLeft($aSRC_FILEPATH[$i], StringInStr($aSRC_FILEPATH[$i], '\', 0, -1) - 1)
Next
_ArraySort($aINF_FILEINFO, 0, 1, 0, 1)
$aINF_FILEINFO[0][0] = UBound($aINF_FILEINFO) - 1

For $i = 2 To $aINF_FILEINFO[0][0]
    $aSRC_DISKFILE = IniReadSection($aINF_FILEINFO[$i][0], 'SourceDisksFiles')
        If @error Then ContinueLoop
    For $j = 1 To $aSRC_DISKFILE[0][0]
        If FileExists($aINF_FILEINFO[$i][3] & '\' & $aSRC_DISKFILE[$j][0]) Then
            FileCopy($aINF_FILEINFO[$i][3] & '\' & $aSRC_DISKFILE[$j][0], $aINF_FILEINFO[$i][4] & '\' & $aSRC_DISKFILE[$j][0], 9)
        EndIf
    Next
    FileCopy($aINF_FILEINFO[$i][0], StringReplace($aINF_FILEINFO[$i][0], $aINF_FILEINFO[$i][3], $aINF_FILEINFO[$i][4]), 9)
Next

For $i = 1 To $aINF_FILEINFO[0][0]
    If FileExists($aINF_FILEINFO[$i][3]) Then
        DirRemove($aINF_FILEINFO[$i][3], 1)
    EndIf
Next

Func _FNC_INFCLEAN($sINF_CLASSNAME)
    $sINF_CLASSNAME = StringStripWS($sINF_CLASSNAME, 7)
    $sINF_CLASSNAME = StringReplace($sINF_CLASSNAME, '"', '')
    $sINF_CLASSNAME = StringReplace($sINF_CLASSNAME, '%', '')
    Return $sINF_CLASSNAME
EndFunc

 

Edited by trashy

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

Hey Subz this makes absolutely no sense!

I always try to test for all scenarios in all environments (PE and Windows OS)

I have 3 hard drive partitions , 2  32 bit win 7 and a 64 bit Win 7. All the testing done so far was extracting drivers from online partition.

Extracting Drivers from Offline Windows partition driver copy fails to get about half the drivers. I even ran DISM from cmd line to extract drivers and your original script to copy with the same result. I have tested this scenario from PE an Windows OS and it really has me baffled. Out of 10 driver folders only copying 6.

I have a hunch it may be Windows 7. Driver export was introduced in Win 8 but I could not get it to work on Win 7 till I used DISM 10. Could you test from PE or something on Windows 10 offline

Edited by trashy

Share this post


Link to post
Share on other sites

#20 ·  Posted

Hi Trashy

I can confirm that Dism 6.x doesn't include /Export-Driver switch, can confirm Dism 10.x does and also works on Windows 7 Online/Offline.  Please note that the /Export-Driver only exports 3rd party drivers.  Is that the information you were after?

Cheers

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now