Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (02/20/09)
How Do I Determine the Versions of Several Executable Files Not Registered in the Registry?
Hey, Scripting Guy! I need your help. I need to know the version of several executable files not registered in the registry. I can find the version of a single executable by using the following code.
Set objFSO = CreateObject("Scripting.FileSystemObject") Wscript.Echo objFSO.GetFileVersion("C:\... nameofexefile")
But I need to “scan” several directories (or all Drive C:\).
– UG
Hi UG,
What you need to do is to use a technique called recursion. When you recurse through something, you basically use a subroutine that will call itself. We need to do a couple of things. First we need to connect to your target folder. We then need to get a collection of all the files in that folder and check them out. After we have done that, we next need to get the subfolders. We then pass the subfolders back to the subroutine, get the files and do it all over again. We will continue to do this until we have checked out all the files. Here is a script, named GetFileVersionInfoRecurse.vbs that will do that.
strTarget = "c:\fso" Set objFSO = CreateObject("Scripting.FileSystemObject") subRecursiveFolders objFSO.GetFolder(strTarget) Sub subRecursiveFolders(Folder) Set colFiles = Folder.files For Each file In colFiles WScript.Echo file.path ver = objFSO.GetFileVersion(file.path) If Len(ver) Then WScript.Echo ver Else WScript.Echo "No version information available." End If Next 'for each file For Each objFolder In Folder.subFolders subRecursiveFolders objFolder Next End Sub
How Do I Determine Who Has a Particular File Open?
Hey, Scripting Guy! I have been trawling the net for days trying to find a way to determine who has a file open. How do I script this?
– KP
Hi KP,
There is not really a good way to get this information, and it is not always reliable. But we can use ADSI to obtain this information. On Windows Vista this script needs to run with admin rights. The ListUsedResources.vbs script uses the WinNT provider to connect to the local computer account, and to return what is called an IadsFileServiceOperations interface. This interface is documented on MSDN. When we call the Resources method, it returns a collection of IadsResource objects. These objects are also documented on MSDN. Here is the ListUsedResources.vbs script.
Set fso = GetObject("WinNT://Mred1/LanmanServer") For Each r In fso.resources WScript.Echo "User " & r.user WScript.Echo vbTab & "Resource path: " & r.Path WScript.Echo vbTab & "Resource Lock count: " & r.lockCount Next
How Do I Execute Different Commands on Different Servers but from the Same Input File?
Hey, Scripting Guy! I need to create a script that connects to several remote servers, using an input file like servers.txt with one hostname per line. And then I want it to execute a specific command, using the command prompt. I’m using VBScript; I know how to write the script and there are many examples on Script Center, but what I was asked is to have the same input file with the server name separated using a semicolon or a comma and the command to be run. So we’ll have something that looks like the following:
Server1;ping 192.168.1.1 Server2;net use t: \\server4\shares
All this data will be written on servers.txt. Is there a script that can do it? You know, the script will read each line and execute the command on that server. When it reads the next line, it should run another command on a different server, but both server name and command will be in the same input file. I know I can do it using two separate input files, such as servers.txt and commands.txt, but for security reasons I must read this info from the same file. Is it possible?
– AG
Hi AG,
Of course it is possible. What you want to do is to read a text file line by line, and then split the line into an array. You can then connect to server in element 0 and run the command from element 1. Here is a link that talks about working with text files.
We’ll assume your text file looks something like this:
You can read the text file by using the readline method from the FileSystemObject.You can then use the split function to break each line into an array. After you have an array, you can use element 0 to refer to the computer and element 1 to refer to the command. You can then execute each command as you work your way through the file. This technique is illustrated in this script:
Const ForReading = 1 Set objShell = WScript.CreateObject("WScript.Shell") Set objFSO = CreateObject("Scripting.FileSystemObject") Set objTextFile = objFSO.OpenTextFile("c:\fso\arycommand.txt", ForReading) Do Until objTextFile.AtEndOfStream strNextLine = objTextFile.Readline arrServiceList = Split(strNextLine , ",") Wscript.Echo "Server name: " & arrServiceList(0) For i = 1 to Ubound(arrServiceList) Wscript.Echo "Command: " & arrServiceList(i) Set objExecObject = objShell.Exec("cmd /c " & arrServiceList(i)) Do While Not objExecObject.StdOut.AtEndOfStream strText = objExecObject.StdOut.ReadLine() Wscript.Echo strText Loop Next Loop
How Can I Write to a File What I Can Already Write to the Screen?
Hey, Scripting Guy! How come I can output stuff to my screen with no problem, but when I try to write it to a file (htm, csv, or text), all I get are blank lines. What’s the deal with that? My code is seen here.
Get-ChildItem $inPath -Recurse -ErrorAction Continue | foreach{ $_.fullname | Get-Acl | select path -expand access | where {$_.IdentityReference -like "Domain*"} | ft path, IdentityReference -autosize $i++ } Write-Host "Number of files: " $i
– GE
Hi GE,
In general, the Windows PowerShell team recommends against using Write-Host unless you need to use one of the parameters it provides such as coloring. What is happening is that Write-Host basically interrupts the pipeline, and there is no passthrough parameter for Write-Host. Here is code that works:
Get-ChildItem $inPath -Recurse -ErrorAction Continue | Foreach-object { $_.fullname | Get-Acl | Select-Object path -expand access | Where-object {$_.IdentityReference -like "Domain*"} | Format-Table path, IdentityReference -autosize $i++ } "Number of files: $i" | Out-File -filepath c:\fso\filecount.txt notepad "c:\fso\filecount.txt"
Well, that is it for this week’s Quick-Hits Friday. It is also the end of another week. Have a safe and productive weekend, and we will see you here next week. Take care.
Ed Wilson and Craig Liebendorfer, Scripting Guys
0 comments