Windows

Extract Drivers

This script will extract all drivers from a computer and copy them to a folder structure organized by type. It is language dependent and currently works for Danish and English Operating System language.

Option Explicit

Dim WshShell, oExec
Set WshShell = CreateObject("WScript.Shell")

Set oExec = WshShell.Exec("Dism.exe /online /get-drivers")

WScript.Echo "Started, Get drivers"

Dim iCounter
iCounter = 0
Do While oExec.Status = 0 And iCounter < 600
	WScript.Sleep 100
	iCounter = iCounter + 1
Loop

WScript.Echo "Execute time: " & iCounter / 10 & " Sec."
WScript.Echo "Exit Code: " & oExec.ExitCode

Dim sText, sDriverList
Dim aDriverList()
Dim iDriversCount
iDriversCount = 0
Do While Not oExec.StdOut.AtEndOfStream
	sText = oExec.StdOut.ReadLine()
	If Left(sText,17) = "Published Name : " Or Left(sText,17) = "Udgivelsesnavn : " Then
		ReDim Preserve aDriverList(iDriversCount)
		aDriverList(iDriversCount) = Trim(Right(sText,Len(sText)-17))
		iDriversCount = iDriversCount + 1
	End If
Loop

Dim sElement
Dim aOEMDriverPaths(), aOEMDriverClasses(), aOEMDriverVersion()

WScript.Echo "Number of OEM Drivers: " & iDriversCount

iDriversCount = 0
For Each sElement In aDriverList
	
	Set oExec = WshShell.Exec("Dism.exe /online /get-driverInfo:" & sElement)

	WScript.Echo "Started, get info for driver: " & sElement

	iCounter = 0
	Do While oExec.Status = 0 And iCounter < 100
		WScript.Sleep 100
		iCounter = iCounter + 1
	Loop

	WScript.Echo "Execute time: " & iCounter / 10 & " Sec."
	WScript.Echo "Exit Code: " & oExec.ExitCode

	Do While Not oExec.StdOut.AtEndOfStream
		sText = oExec.StdOut.ReadLine()
		If Left(sText,20) = "Driver Store Path : " Then
			ReDim Preserve aOEMDriverPaths(iDriversCount)
			aOEMDriverPaths(iDriversCount) = Trim(Right(sText,Len(sText)-20))
		End If
		If Left(sText,22) = "Sti til driverlager : " Then
			ReDim Preserve aOEMDriverPaths(iDriversCount)
			aOEMDriverPaths(iDriversCount) = Trim(Right(sText,Len(sText)-22))
		End If
						    
		If Left(sText,13) = "Class Name : " Or Left(sText,13) = "Klassenavn : "Then
			ReDim Preserve aOEMDriverClasses(iDriversCount)
			aOEMDriverClasses(iDriversCount) = Trim(Right(sText,Len(sText)-13))
		End If
		If Left(sText,10) = "Version : " Then
			ReDim Preserve aOEMDriverVersion(iDriversCount)
			aOEMDriverVersion(iDriversCount) = Trim(Right(sText,Len(sText)-10))
			iDriversCount = iDriversCount + 1
		End If
	Loop
Next

Dim sScriptPath, sDriversDestinationPath
sScriptPath = Left(wscript.scriptfullname, Len(wscript.scriptfullname) - Len(wscript.scriptname))

Wscript.echo sScriptPath

Dim sComputer, oWMIService, cItems, oItem, sManufacturer, sModel
sComputer = "." 
Set oWMIService = GetObject("winmgmts:\\" & sComputer & "\root\CIMV2") 
Set cItems = oWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem",,48) 
For Each oItem in cItems
    sManufacturer = oItem.Manufacturer
    sModel = oItem.Model
Next

WScript.Echo "Number of OEM Drivers: " & iDriversCount

Dim sInfFileName, sDriverVersion, sDriverCopySource, sDriverCopyDistination, iWaitCounter


For iCounter = 0 To iDriversCount-1

	sInfFileName = Right(aOEMDriverPaths(iCounter),Len(aOEMDriverPaths(iCounter))-InstrRev(aOEMDriverPaths(iCounter),"\",-1,vbTextCompare))
	sInfFileName = Left(sInfFileName,Len(sInfFileName)-4)
	sDriverVersion = aOEMDriverVersion(iCounter)
	sDriversDestinationPath = sScriptPath & "Drivers\" & sManufacturer & "\" & sModel & "\"
	sDriverCopySource = Left(aOEMDriverPaths(iCounter),InstrRev(aOEMDriverPaths(iCounter),"\",-1,vbTextCompare))
	sDriverCopyDistination = sDriversDestinationPath & aOEMDriverClasses(iCounter) & "\" & sInfFileName & "_" & sDriverVersion

	WScript.echo "Copy Driver: " & aOEMDriverClasses(iCounter) & " " & sInfFileName & " " & sDriverVersion

	CopyFolder sDriverCopySource, sDriverCopyDistination, "Precompiled Setup Information"
Next

Function CopyFolder(sSourceFolder, sDestinationFolder, sExcludeType)
	SearchSubFolders sSourceFolder, sDestinationFolder, sExcludeType
End Function

Sub SearchSubFolders(sSourceFoldersPath, sDestFoldersPath, sExcludeType)

	Dim oFileSystem, oFolder, oFile, aExcludeType, bExclude, sElement
	Set oFileSystem = CreateObject("Scripting.FileSystemObject")
	aExcludeType = Split(sExcludeType,",",-1,vbTextCompare)

	'** Søg i under mapper ************************************************************
	Set oFolder = oFileSystem.getFolder(sSourceFoldersPath)
	For Each ofile in oFolder.SubFolders
		SearchSubFolders sSourceFoldersPath & "\" & oFile.name, sDestFoldersPath & "\" & oFile.name, sExcludeType
	Next

	'** Kopier filer i mappe **********************************************************
	For Each oFile in oFolder.Files

		bExclude = False
		For Each sElement In aExcludeType
			If UCase(oFile.Type) = UCase(sElement) Then
				bExclude = True
			End If
		Next
		If Not bExclude Then
			CopyFile sSourceFoldersPath, sDestFoldersPath, oFile.name
		End If
	Next
	Set oFolder = Nothing
	Set oFileSystem = nothing

End Sub


Function CopyFile(sSourceFilePath, sDestFilePath, sFile)

	Dim oFileSystem, oCopyFile, oCopyFileDest, iSecondsDateDiff
	Set oFileSystem = CreateObject("Scripting.FileSystemObject")

	'** Kontroller om destinations filen findes ****************************************
	If oFileSystem.FileExists(sDestFilePath & "\" & sFile) Then

		'** Destinations fil eksisterer, kontroller om kilde fil er nyere **********
		Set oCopyFile = oFileSystem.GetFile(sSourceFilePath & "\" & sFile)
		Set oCopyFileDest = oFileSystem.GetFile(sDestFilePath & "\" & sFile)
		iSecondsDateDiff = DateDiff("s", oCopyFile.DateLastModified, oCopyFileDest.DateLastModified)
		If iSecondsDateDiff < 0 Then

			'** Kilde Fil er nyere, kopier fil *********************************
			On Error resume Next
			oCopyFile.Copy (sDestFilePath & "\" & sFile)
			If Err.Number = 0 Then
				'wscript.echo "File copied: "  & sSourceFilePath & "\" & sFile
			Else
				'** Fejl i kopiering, log fejl *****************************
				wscript.echo "ERROR " & Err.Number & " copy file: " & sSourceFilePath & "\" & sFile
			End If
			On Error Goto 0

		End If
		Set oCopyFile = nothing
		Set oCopyFileDest = nothing
	Else

		'** Destination findes ikke, kopier fil ************************************
		Set oCopyFile = oFileSystem.GetFile(sSourceFilePath & "\" & sFile)
		CreateFolderTree(sDestFilePath)
		On Error resume Next
		oCopyFile.Copy (sDestFilePath & "\" & sFile)

		'** Slet kilde fil, hvis kopiering gik godt ********************************
		If Err.Number = 0 Then
			'wscript.echo "File copied: "  & sSourceFilePath & "\" & sFile
		Else
			'** Fejl i kopiering, log fejl *************************************
			wscript.echo  "Error " & Err.Number & " copy file: " & sSourceFilePath & "\" & sFile

		End If
		On Error Goto 0
		Set oCopyFile = nothing
	End If
	Set oFileSystem = nothing
End Function


'****************************************************************************** 
Function CreateFolderTree(strInput)
	Dim objFileSystemObject
	Set objFileSystemObject = CreateObject("Scripting.FileSystemObject")
	If Not objFileSystemObject.FolderExists(strInput) Then 
		Dim arrFolderPath,intFolder,strFolderTree
		arrFolderPath = Split(strInput,"\")
		For intFolder = 0 To UBound(arrFolderPath)
			strFolderTree = strFolderTree & arrFolderPath(intFolder) & "\"
			If intFolder > 1 Then 
				If Not objFileSystemObject.FolderExists(strFolderTree) Then
					objFileSystemObject.CreateFolder(strFolderTree)
				End If
			End If
		Next
		CreateFolderTree = True
	Else
		CreateFolderTree = False
	End If
	Set objFileSystemObject = nothing
End Function

Rebuild a corrupt WMI repository

If i run into client computers that have issues with WMI i usually run through these steps:

Run this command to verify WMI:

winmgmt /verifyrepository

If the above command returns “inconsistent” then i would run the following command:

winmgmt /salvagerepository

Then i would use verifyrepository again to check the state. If it is still “inconsistent” then i would run the following command:

winmgmt /resetrepository

This will stop the WMI service and rename the repository (C:\Windows\System32\wbem\repository) and start the WMI service.

This should resolve the WMI issues.

In case you are in a SCCM environment the affected computer would need its SCCM client reinstalled.

Uninstall Microsoft Software Update deployed with SCCM

I recently had to uninstall a Software Update deployed by SCCM 2012 on a Windows 10 client. Before when running SCCM 2007 i used to run WUSA with the following syntax:

wusa.exe / uninstall / kb: <KBnumber> /quiet /norestart

This didnt work  with the /quiet parameter so instead i had to use DISM as i need to be able to uninstall it silently.

DISM takes the packageName of the Software Update as input which can be found by running the following command on a client which have the Software Update installed:

dism /online /get-packages /format:table

Deployment Image Servicing and Management tool
Version: 10.0.10586.0

Image Version: 10.0.10586.0

Packages listing:


--------------------------------------------------------------------------------------------------------- | --------------- | --------------- | ----------------
Package Identity                                                                                          | State           | Release Type    | Install Time    
--------------------------------------------------------------------------------------------------------- | --------------- | --------------- | ----------------
Microsoft-Windows-Client-LanguagePack-Package~31bf3856ad364e35~amd64~da-DK~10.0.10586.0                   | Installed       | Language Pack   | 13-02-2016 16:58
Microsoft-Windows-DiagTrack-Internal-Package~31bf3856ad364e35~amd64~~10.0.10586.0                         | Installed       | Feature Pack    | 30-10-2015 07:26
Microsoft-Windows-Foundation-Package~31bf3856ad364e35~amd64~~10.0.10586.0                                 | Installed       | Foundation      | 30-10-2015 07:26
Microsoft-Windows-InsiderHub-Package~31bf3856ad364e35~amd64~~10.0.10586.0                                 | Installed       | OnDemand Pack   | 13-02-2016 17:02
Microsoft-Windows-LanguageFeatures-Basic-da-dk-Package~31bf3856ad364e35~amd64~~10.0.10586.0               | Installed       | OnDemand Pack   | 13-02-2016 17:02
Microsoft-Windows-LanguageFeatures-Basic-en-us-Package~31bf3856ad364e35~amd64~~10.0.10586.0               | Installed       | OnDemand Pack   | 13-02-2016 17:02
Microsoft-Windows-LanguageFeatures-Handwriting-da-dk-Package~31bf3856ad364e35~amd64~~10.0.10586.0         | Installed       | OnDemand Pack   | 13-02-2016 17:02
Microsoft-Windows-LanguageFeatures-OCR-da-dk-Package~31bf3856ad364e35~amd64~~10.0.10586.0                 | Installed       | OnDemand Pack   | 13-02-2016 17:02
Microsoft-Windows-LanguageFeatures-OCR-en-us-Package~31bf3856ad364e35~amd64~~10.0.10586.0                 | Installed       | OnDemand Pack   | 13-02-2016 17:02
Microsoft-Windows-NetFx3-OnDemand-Package~31bf3856ad364e35~amd64~~10.0.10586.0                            | Installed       | OnDemand Pack   | 11-04-2016 14:54
Microsoft-Windows-Prerelease-Client-Package~31bf3856ad364e35~amd64~da-DK~10.0.10586.0                     | Installed       | Language Pack   | 13-02-2016 16:58
Microsoft-Windows-Prerelease-Client-Package~31bf3856ad364e35~amd64~~10.0.10586.0                          | Installed       | Feature Pack    | 30-10-2015 07:26
Microsoft-Windows-Security-SPP-Component-SKU-Enterprise-GVLK-Package~31bf3856ad364e35~amd64~~10.0.10586.0 | Installed       | Feature Pack    | 13-02-2016 17:20
Package_for_KB3135173~31bf3856ad364e35~amd64~~10.0.1.2                                                    | Installed       | Security Update | 13-02-2016 17:13
Package_for_KB3136561~31bf3856ad364e35~amd64~~10.0.1.0                                                    | Installed       | Update          | 13-02-2016 17:13
Package_for_KB3140741~31bf3856ad364e35~amd64~~10.0.1.0                                                    | Installed       | Update          | 11-04-2016 14:35
Package_for_KB3144756~31bf3856ad364e35~amd64~~10.0.1.0                                                    | Installed       | Security Update | 11-04-2016 14:35
Package_for_KB3149135~31bf3856ad364e35~amd64~~10.0.1.1                                                    | Installed       | Update          | 24-06-2016 15:03
Package_for_KB3154132~31bf3856ad364e35~amd64~~10.0.1.0                                                    | Installed       | Security Update | 24-06-2016 10:01
Package_for_KB3157993~31bf3856ad364e35~amd64~~10.0.1.0                                                    | Installed       | Security Update | 24-06-2016 09:49
Package_for_RollupFix~31bf3856ad364e35~amd64~~10586.218.1.4                                               | Superseded      | Security Update |                 
Package_for_RollupFix~31bf3856ad364e35~amd64~~10586.318.1.7                                               | Install Pending | Security Update | 28-06-2016 12:39

The operation completed successfully.

From the list find the Package Identity Name of the Software Update.

Run this command to uninstall the KB3144756 silently:

DISM.exe /Online /Remove-Package /PackageName:Package_for_KB3144756~31bf3856ad364e35~amd64~~10.0.1.0 /quiet /norestart

It might require a reboot for the update to be fully removed.

Track system Startup, Shutdown, Uptime and much more using Windows logs Event ID’s

The following Event ID’s in the System log are nice to know for various debugging scenarios on the client computers.

1074 – Information about program or user that initiated restart/shutdown

6005 – Startup time

6006 – Shutdown time

6013 – System uptime

Using the “Filter Current Log” feature allows you to search for occurences of the events you want to dig into.

Using a PAC file to restrict access to Websites

If you want to control which websites can be accessed from one or more computers a PAC file solution can be used.

The PAC file is a fairly simple file containing information on which sites can or cant be accessed – depending on what your needs are. This means you can set up a solution where all websites can be accessed except from the ones in your PAC file or you can setup a solution where all websites are blocked except from the ones in the PAC file.

In Internet Explorer you then have to enable the “Use automatic configuration script” under Tools > Internet Options > Connections > LAN Setting and then point to the location of your PAC file. The PAC file can be placed both locally or on a webserver.

Example of a PAC file where only the sites *.google.com, *.facebook.com and *.msn.com can be accessed (Proxy.pac):

function FindProxyForURL(url, host)
 {
// variable strings to return
 var access = "PROXY servername.domain.com:8080";
 var noaccess = "PROXY 127.0.0.1:80";
 if (shExpMatch(host, "*.google.com")) { return access; }
 if (shExpMatch(host, "*.facebook.com")) { return access; }
 if (shExpMatch(host, "*.msn.com")) { return access; }
 // Proxy anything else
 return noaccess;
 }

Example of a PAC file where the above sites are blocked and all other sites can be accessed.

function FindProxyForURL(url, host)
 {
// variable strings to return
 var access = "PROXY servername.domain.com:8080";
 var noaccess = "PROXY 127.0.0.1:80";
 if (shExpMatch(host, "*.google.com")) { return noaccess; }
 if (shExpMatch(host, "*.facebook.com")) { return noaccess; }
 if (shExpMatch(host, "*.msn.com")) { return noaccess; }
 // Proxy anything else
 return access;
 }

 

Bootable USB

This guide will tell you how to make a bootable USB. To make the bootable USB you need to use DISKPART which comes with Windows. Its important tho that you use either Windows Vista or Windows 7 otherwise DISKPART cant detect your USB key as a drive.

Start your command prompt and type diskpart – this will open a new diskpart window. The rest is shown in the screendump below.

Change Shutdown Setting

When doing automated reboots using shutdown.exe in my scripts i sometimes need to change back the default shutdown option so the user will have “Shutdown” as the default selection in the shutdown box.

The shutdown setting determining the default shutdown option – (log off, shutdown, restart, standby, hibernate, disconnect) can be found in the registry under current user settings.

Key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer
Value: Shutdown Setting
Type: REG_DWORD
Radix: Hex
Data: 00000002

The possible values for Shutdown Setting are:

00000001 = Log Off
00000002 = Shut Down
00000004 = Restart
00000010 = Stand By
00000020 = Stand By (with wakeup events disabled)
00000040 = Hibernate
00000080 = Disconnect (only available in Terminal Services sessions)

Slipstream updates into your Office 2007 installation

I recently had to update a standard Office 2007 installation with SP2. This is easily done with a few commandlines assuming that you have both downloaded the SP2 update and have the Office 2007 installation files already avaliable.

Locate the Updates folder among your Office 2007 installation files. This is the folder where we want the SP2 files to end up. In my example the path to the updates folder is :

E:\Office2007\Updates

I placed the SP2 update in a temporary folder:

E:\Temp\Office2007-SP2-Update\office2007sp2-kb953195-fullfile-da-dk.exe

To extract the SP2 update and thereby slipsteam the SP2 update into the Office 2007 installation simply type the following:

E:\Temp\Office2007-SP2-Update\office2007sp2-kb953195-fullfile-da-dk.exe /extract:”E:\Office2007\Updates”

Accept the licence agreement and follow the steps until you get a confirmation that the installation is complete.

Now you are ready to install Office 2007 SP2.

If you want to slipsteam other Windows updates into your Office 2007 installation files simply repeat the steps above only by replacing the update you want to slipsteam.

Using SubInACL to grant permissions to a folder and its subfolders and files

Recently i had to delete a lot of temporary folders on a large number of domain computers. A GPO had caused a number of folders to be created in the root of C each time a user logged onto a computer. After having sorted the GPO i had to find a way to delete all the folders again. The tricky part was that the folders had different owners and thus different permissions assigned so they could not all be deleted by the current user.

Microsofts command-line tool SubInACL proved to be exactly the tool for the job and i could easily make a vbs script which could do the cleanup job for me at logon – no matter who was logged on.

I simply used SubInACL to give the current user Full Access to all the folders and their subfolders and files by looping through the folder structure and subsequently deleting the folders which matched my deleting criteria.

The syntax i used to give the current user full access a folder and its subfolders and files was this:

subinacl.exe /verbose=1 /subdirectories c:\folder\*.* /grant=Current user=F

Look up the MAC address on a remote computer with GETMAC

To look up a MAC Address on a remote computer you can use the build in windows tool called GETMAC.

Except from the MAC Address GETMAC can also supply information about network protocols and network adapter.

Example:

To get the MAC address of the remote computer PC123456 you simply type the follwing:

getmac /s PC123456

To get full details about adapter name and connection names aswell you simple add the parameter /v.

getmac /s \\PC123456 /v

Full documentation

http://technet.microsoft.com/en-us/library/ff961509