Ok, here is my current script, i built it after the audio solution in attempt to make dll hell a breeze. its written in autoit and store on a network drive that i mount on boot.
I have install.wim extracted to \Source, and another Folder on the netdrive called \Deps.
here is what the script does...
-If procmon is running, it asks it to terminate.
-Starts up procmon with a predefined filter, and hidden in the background.
-Gets the handle of the window, then the listview of procmon.
-Next we store each new value in an array, of course excluding duplicates.
-Then after no more entires have been added, then we check those dependencies. (If the file exists in on X: ignore it, if the file does not exist in the source...again ignore it.)
-Every 200,000 events in procmon, the script clicks the button "Clear" then "Start/Stop Caputre" twice.
Note: The Filter Includes only "NAME NOT FOUND" and Anything under X:\Windows.
It does exclude various redundant entries like *.manifest, *.mui.DLL, etc, entries we dont really need.
So basically, you type for example mmc.exe in cmd.exe
well, since its not found, GetDeps will see that, and copy mmc.exe and mmc.exe.mui to X:\Windows\System32 and \Deps\Windows\System32.
Then you will try to run mmc again, which it will fail due to missing Dlls, which are in turn copied. Run it again!
Repeat the process until mmc.exe loads up.
The same process can be achieved with the registry entries. However, we would need to build a filter for redundant entries.
Here is the code:
#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=y
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Run_Au3Stripper=y
#Au3Stripper_Parameters=/rsln
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include <WinAPIProc.au3>
#Include <Array.au3>
#include <GuiListView.au3>
#include <String.au3>
Global $sExec
Global $aDeps[0][2]
Global $sSrc=@ScriptDir&"\Source"
Global $sDep=@ScriptDir&"\Deps"
If @OSArch="X64" Then
$sExec="ProcMon64.exe"
Else
$sExec="ProcMon.exe"
EndIf
While ProcessExists($sExec)
RunWait($sExec&" /terminate")
ProcessClose($sExec)
WEnd
$iPID=Run($sExec&" /acceptEula /LoadConfig ProcmonConfiguration.pmc /Quiet",@ScriptDir,@SW_HIDE)
ProcessWait($iPID)
;ConsoleWrite("iPID="&$iPID&@CRLF)
OnAutoItExitRegister("_Exit")
Global $aWnd=_WinAPI_EnumProcessWindows($iPID,False)
If Not IsArray($aWnd) Then _Exit()
Global $hWnd
For $i=1 to $aWnd[0][0]
If $aWnd[$i][1]="PROCMON_WINDOW_CLASS" Then
$hWnd=$aWnd[$i][0]
EndIf
Next
;ConsoleWrite("hWnd="&$hWnd&@CRLF)
Global $hListView=ControlGetHandle($hWnd,"","SysListView321")
;ConsoleWrite("hListView="&$hListView&@CRLF)
$iCols=_GUICtrlListView_GetColumnCount($hListView)
Local $iMax=0
Local $iLast=0
AdlibRegister("_EventWatch",250)
While Sleep(125)
$iMax=_GUICtrlListView_GetItemCount($hListView)
If $iMax>$iLast And $iMax>0 Then
For $i=$iLast to $iMax
$sExec=_GUICtrlListView_GetItemText($hListView,$i,1)
$sPath=_GUICtrlListView_GetItemText($hListView,$i,4)
If $sExec=@AutoItExe Then ContinueLoop
;~ if StringLeft($sPath,2)="HK" Then
;~ ConsoleWrite("[Reg] "&$sPath&@CRLF)
;~ EndIf
_AddDep($sPath)
Next
$iLast=$iMax
_ResolveDeps()
EndIf
If Not ProcessExists($iPID) Then ExitLoop
WEnd
_Exit()
Func _Exit()
ProcessClose($iPID)
EndFunc
Func _AddDep($sPath)
If $sPath="" Then Return False
$sPath=StringTrimLeft($sPath,3)
$iMax=UBound($aDeps,1)
For $i=0 to $iMax-1
If $aDeps[$i][0]=$sPath Then Return
Next
If FileExists("X:\"&$sPath) Then Return
ReDim $aDeps[$iMax+1][2]
$aDeps[$iMax][0]=$sPath
$aDeps[$iMax][1]=0
ConsoleWrite("[Chk] "&$sPath&@CRLF)
EndFunc
Func _ResolveDeps()
$iMax=UBound($aDeps,1)
For $i=0 to $iMax-1
If $aDeps[$i][1]=1 Or $aDeps[$i][1]=3 Then ContinueLoop
If FileExists("X:\"&$aDeps[$i][0]) Then
ContinueLoop
Else
$sFile=StringTrimLeft($aDeps[$i][0],StringInStr($aDeps[$i][0],"\",0,-1))
$sPath=StringTrimRight($aDeps[$i][0],StringLen($aDeps[$i][0])-StringInStr($aDeps[$i][0],"\",0,-1)+1)
If not FileExists($sSrc&"\"&$sPath&"\"&$sFile) Then
ConsoleWrite("[Ign] "&$aDeps[$i][0]&@CRLF)
$aDeps[$i][1]=1
ContinueLoop
EndIf
ConsoleWrite("[Cpy] "&$aDeps[$i][0]&"...")
If FileExists($sSrc&"\"&$sPath&"\"&$sFile) Then ConsoleWrite(FileCopy($sSrc&"\"&$sPath&"\"&$sFile,"X:\"&$sPath&"\"&$sFile,1+8))
If FileExists($sSrc&"\"&$sPath&"\en-US\"&$sFile&".mui") Then ConsoleWrite(FileCopy($sSrc&"\"&$sPath&"\en-US\"&$sFile&".mui","X:\"&$sPath&"\en-US\"&$sFile&".mui",1+8))
If FileExists($sSrc&"\"&$sPath&"\"&$sFile) Then ConsoleWrite(FileCopy($sSrc&"\"&$sPath&"\"&$sFile,$sDep&"\"&$sPath&"\"&$sFile,1+8))
If FileExists($sSrc&"\"&$sPath&"\en-US\"&$sFile&".mui") Then ConsoleWrite(FileCopy($sSrc&"\"&$sPath&"\en-US\"&$sFile&".mui",$sDep&"\"&$sPath&"\en-US\"&$sFile&".mui",1+8))
ConsoleWrite(@CRLF)
ConsoleWrite(@CRLF)
$aDeps[$i][1]=1
EndIf
Next
EndFunc
Func _EventWatch()
$iEvents=_GetEventCount()
If $iEvents>=200000 Then
Call("_Clear")
_GetEventCount()
EndIf
EndFunc
Func _GetEventCount()
Local $iEvents=0
$sStatus=StatusbarGetText($hWnd,"",1)
$iEvents=StringRegExp($sStatus,"The current filter excludes all (\d{1,3}(?:,\d{1,3})?) events",1)
If @Error Then
$iEvents=StringRegExp($sStatus,"Showing \d{1,3}(?:,\d{1,3})? of (\d{1,3}(?:,\d{1,3})?) events",1)
If @Error Then
$iEvents=0
Return $iEvents
Else
$iEvents=StringReplace($iEvents[0],",","")
EndIf
Else
$iEvents=StringReplace($iEvents[0],",","")
EndIf
Return $iEvents
EndFunc
Func _Clear()
AdlibUnRegister("_EventWatch")
ConsoleWrite("[Inf] Clearing Events..."&@CRLF)
ControlClick($hWnd,"","ToolbarWindow321","left",1,16*6,15)
ControlClick($hWnd,"","ToolbarWindow321","left",1,16*8,15)
ControlClick($hWnd,"","ToolbarWindow321","left",1,16*6,15)
AdlibRegister("_EventWatch",250)
EndFunc
A few more notes:
-Procmon64.exe is extracted by procmon.exe in a temp dir when running on an x64 environment.
-Be sure to compile to x64 when using x64 PE/OS.
-to show the procmon window change @SW_HIDE to @SW_SHOW on line 26.
Edited by Biatu, 12 September 2016 - 05:27 PM.