trashy Posted January 6, 2017 Posted January 6, 2017 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!
Developers Jos Posted January 6, 2017 Developers Posted January 6, 2017 (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 January 6, 2017 by Jos SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past.
Subz Posted January 6, 2017 Posted January 6, 2017 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)
trashy Posted January 6, 2017 Author Posted January 6, 2017 (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 January 6, 2017 by trashy
Subz Posted January 6, 2017 Posted January 6, 2017 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.
trashy Posted January 7, 2017 Author Posted January 7, 2017 Subz I may take you up on that with what I've got getting close but also getting in over my head.
Subz Posted January 7, 2017 Posted January 7, 2017 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")
trashy Posted January 7, 2017 Author Posted January 7, 2017 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. expandcollapse popup#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
Subz Posted January 7, 2017 Posted January 7, 2017 (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. expandcollapse popup#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 Edited January 8, 2017 by Subz
trashy Posted January 7, 2017 Author Posted January 7, 2017 (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. Edited January 7, 2017 by trashy
trashy Posted January 7, 2017 Author Posted January 7, 2017 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.
Subz Posted January 8, 2017 Posted January 8, 2017 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.
trashy Posted January 8, 2017 Author Posted January 8, 2017 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.
Subz Posted January 8, 2017 Posted January 8, 2017 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?
trashy Posted January 8, 2017 Author Posted January 8, 2017 (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 January 8, 2017 by trashy
Subz Posted January 8, 2017 Posted January 8, 2017 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.infExample: IniRead('C:\Drivers\prnms001.inf_amd64_10bd6dee10a7dfd0\prnms001.Inf',... Hope that makes sense.
trashy Posted January 8, 2017 Author Posted January 8, 2017 (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 January 8, 2017 by trashy
trashy Posted January 9, 2017 Author Posted January 9, 2017 (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. expandcollapse popup#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 January 9, 2017 by trashy
trashy Posted January 9, 2017 Author Posted January 9, 2017 (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 January 9, 2017 by trashy
Subz Posted January 10, 2017 Posted January 10, 2017 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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now