Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (04/24/09)

Avatar

In This Post
How Can I Create Unique User Permissions on Windows Server 2003 with Group Policy? How Can I Script the Download of Large Binary Files?
How Can I Format Specific Words in a Word Document? How Do I Take Ownership of a File?
How Can I Find Drive Free Space for Volumes on Volume Mount Points? How Do I Get the Time on a Computer?
How Can I Determine Which MAC Address Is Associated with a Network Adapter? How Do I Increment a Number and Retain Its Format?
How Can I Query the Size of a Pagefile Without Changing the Size of the Same Pagefile? How Can I Get a List of Mapped Drives from a Remote Machine?

How Can I Script the Download of Large Binary Files?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! Is there a way I can script the download of large (500MB–2GB+) binary files from a Web site? Oh—and I’m flexible too—it can be in VBScript or Windows PowerShell—your choice! (I am most familiar with VBScript, however.) I have found several VBScript examples showing how to use the xmlhttp object combined with the adodb.stream objects to download binary files. These work okay for smaller files, but they seem to fall apart when trying to do work with large files (for example, running out of memory; it appears it may try to buffer the entire file in memory before writing the contents to file). Please help, oh great and powerful scripter!

– SG

SpacerHey, Scripting Guy! Answer

Hi SG,

I personally use bitsadmin.exe to do this (assuming the Web site supports it). This is the same technology Windows Update uses and therefore the service has to be running. I figure I may as well get something out of it. Take a look at the command-line Help for it. In Windows 7 (and Windows Server 2008 R2), there are Windows PowerShell cmdlets to simplify using it! This article on MSDN talks about the BITSAdmin tool. This article on TechNet has some good examples of BITSAdmin syntax. This article on MSDN has some more examples of BitsAdmin syntax. You can also refer to the command-line Help for some additional information. I learned a cool thing about using BITSadmin a couple of years ago when I was working in Edinburgh, Scotland. I was working on the scripts for the Vista Resource Toolkit, and as a result I needed to get the latest builds of Windows Vista from our servers in Redmond, Washington, each day. This was a sometimes difficult proposition, but luckily when network connectivity failed, I was able to simply restart the job, and it would pick back up from where it left off. Before this, I was using RichCopy, and while that is an awesome tool, it did not do check point restarts. So if the network connection drops out while in the middle of a download, I had to start it all over again. This is no problem if it is a 1 MB file, but if it is a 4 GB file, it can be rather frustrating. Particularly, if you still have to use the file once you have downloaded it.

 

How Do I Take Ownership of a File?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I am trying to take ownership of a file by following the method outlined in this “Hey, Scripting Guy!”article. The script keeps failing. Is there something I need to declare or change to make it work?

– ES

SpacerHey, Scripting Guy! Answer

Hi ES,

I copied the script from that article, and just ran it on my machine. It works just fine. You do not need to declare anything. I had to do the following things to make the script work:

I had to change the path to a folder of which I wish to take ownership.

I had to run the script as an administrator on my Windows Vista computer.

While I was changing things, I also made two improvements to the script:

I moved the folder from being hard-coded in the query into a variable. This will make the script easier to work with and offers the possibility of reading a list of file names of which to take ownership.

I used wscript.echo to print out the return code from the script. This will let you know if the command was successful or not. The revised TakeOwnerShipOfFile.vbs script is seen here:

TakeOwnerShipOfFile.vbs

strComputer = “.”
strFolder = “‘c:\\fso'”
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)
Set colFolders = objWMIService.ExecQuery _
    (“Select * From Win32_Directory Where Name = ” & strFolder )

For Each objFolder in colFolders     wscript.Echo objFolder.TakeOwnershipEx Next

One additional note: On Windows Server 2003 and later, you can use icacls.exe to work with file security. Here is an article on TechNet that talks about using icacls.exe. This Knowledge Base article talks about where to download icacls.exe for Windows Server 2003 (it is already in Windows Server 2008 and Windows Vista).

 

How Do I Get the Time on a Computer?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I need a way to get the time on a computer.

– DR

SpacerHey, Scripting Guy! Answer

Hi DR,

The easiest way to get the time is to use the Now function that is built into VBScript. This is seen here:

WScript.Echo Now

The problem is that it will not work remotely. To get remote time, you can use the WMI class WIN32_LocalTime. This is seen here:

win32_LocalTime.vbs

Option Explicit 
‘On Error Resume Next
dim strComputer
dim wmiNS
dim wmiQuery
dim objWMIService
dim colItems
dim objItem

strComputer = “.” wmiNS = “\root\cimv2” wmiQuery = “win32_LocalTime=@” Set objWMIService = GetObject(“winmgmts:\\” & strComputer & wmiNS) Set objItem = objWMIService.get(wmiQuery) With objItem                 Wscript.echo “Day: ”  & .Day                 Wscript.echo “DayOfWeek: ”  & .DayOfWeek                 Wscript.echo “Hour: ”  & .Hour                 Wscript.echo “Milliseconds: ”  & .Milliseconds                 Wscript.echo “Minute: ”  & .Minute                 Wscript.echo “Month: ”  & .Month                 Wscript.echo “Quarter: ”  & .Quarter                 Wscript.echo “Second: ”  & .Second                 Wscript.echo “WeekInMonth: ”  & .WeekInMonth                 Wscript.echo “Year: ”  & .Year End with

 

How Do I Increment a Number and Retain Its Format?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! Suppose you have a number like 00001.00 and you would like to add one to it, and then have the number reported 00002.00. The FormatNumber function will keep the trailing zeros, but not the leading zeros.

– TB

SpacerHey, Scripting Guy! Answer

Hi TB,

I started working on an example of how to do this, and then I decided to ask my buddy Michael Murgolo who is a senior consultant at Microsoft and author of Elevation Power Toys. As it turns out, he already had a nice function he was willing to share with us. Woohoo! Thanks, Michael.

PadString.vbs

‘//////////////////////////////////////////////////////////////////////////////
‘ PadString
‘ This function pads a string with a padding character to create a new string
‘ of a defined length
‘
‘ Inputs:
‘   strInput          String to be padded in necessary
‘   intReturnLength   Required padded string length
‘   strPadChar        Character to be used as padding
‘   blnPadAtEnd       If true, add the padding characters to the end of the string
‘                     If false, add the padding characters to the beginning of the string
‘
‘ Returns:
‘   padded string
‘
Function PadString(strInput, intReturnLength, strPadChar, blnPadAtEnd)

                Do While NOT(len(strInput) >= intReturnLength)                                 If blnPadAtEnd = True Then             strInput = strInput & strPadChar         Else             strInput = strPadChar & strInput         End If                 loop                 PadString = strInput

End Function

 

How Can I Get a List of Mapped Drives from a Remote Machine?

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! In your article dated October 2005 titled, “How Can I Determine Which Drives Are mapped to Network Shares?” it says: “As usual, you can modify this script to run against a remote computer simply by assigning the name of that machine to the variable strComputer. But when I try it, there are no results—are you sure you can run the (“Select * From Win32_LogicalDisk Where DriveType = 4”) WMI query against a remote machine? I’d really like to know how to get a list of mapped drives from a remote machine.

– CH

SpacerHey, Scripting Guy! Answer

Hi CH,

I did not write the article back in 2005, so I am not sure of the environment. I can tell you that when using Windows Server 2008 and Windows Vista, you cannot use the code mentioned in the article. I tested the script on my two virtual machines, one that runs Windows Server 2003 and the other Windows XP. It does return data, so the article was correct when it was written. At any rate, you can use the WIN32_MappedLogicalDisk WMI class, and it will return share information from a remote server or work station. This WMI class is available beginning with Windows XP. A simple script using this WMI class is seen here:

MappedLogicalDisk.vbs

On Error Resume Next
Dim strComputer
Dim objWMIService
Dim propValue
Dim objItem
Dim SWBemlocator
Dim UserName
Dim Password
Dim colItems

strComputer = “.” UserName = “” Password = “” Set SWBemlocator = CreateObject(“WbemScripting.SWbemLocator”) Set objWMIService = SWBemlocator.ConnectServer(strComputer,”root\CIMV2″,UserName,Password) Set colItems = objWMIService.ExecQuery(“Select * from Win32_MappedLogicalDisk”,,48) For Each objItem in colItems WScript.Echo “Access: ” & objItem.Access WScript.Echo “Availability: ” & objItem.Availability WScript.Echo “BlockSize: ” & objItem.BlockSize WScript.Echo “Caption: ” & objItem.Caption WScript.Echo “Compressed: ” & objItem.Compressed WScript.Echo “ConfigManagerErrorCode: ” & objItem.ConfigManagerErrorCode WScript.Echo “ConfigManagerUserConfig: ” & objItem.ConfigManagerUserConfig WScript.Echo “CreationClassName: ” & objItem.CreationClassName WScript.Echo “Description: ” & objItem.Description WScript.Echo “DeviceID: ” & objItem.DeviceID WScript.Echo “ErrorCleared: ” & objItem.ErrorCleared WScript.Echo “ErrorDescription: ” & objItem.ErrorDescription WScript.Echo “ErrorMethodology: ” & objItem.ErrorMethodology WScript.Echo “FileSystem: ” & objItem.FileSystem WScript.Echo “FreeSpace: ” & objItem.FreeSpace WScript.Echo “InstallDate: ” & objItem.InstallDate WScript.Echo “LastErrorCode: ” & objItem.LastErrorCode WScript.Echo “MaximumComponentLength: ” & objItem.MaximumComponentLength WScript.Echo “Name: ” & objItem.Name WScript.Echo “NumberOfBlocks: ” & objItem.NumberOfBlocks WScript.Echo “PNPDeviceID: ” & objItem.PNPDeviceID for each propValue in objItem.PowerManagementCapabilities WScript.Echo “PowerManagementCapabilities: ” & propValue next WScript.Echo “PowerManagementSupported: ” & objItem.PowerManagementSupported WScript.Echo “ProviderName: ” & objItem.ProviderName WScript.Echo “Purpose: ” & objItem.Purpose WScript.Echo “QuotasDisabled: ” & objItem.QuotasDisabled WScript.Echo “QuotasIncomplete: ” & objItem.QuotasIncomplete WScript.Echo “QuotasRebuilding: ” & objItem.QuotasRebuilding WScript.Echo “SessionID: ” & objItem.SessionID WScript.Echo “Size: ” & objItem.Size WScript.Echo “Status: ” & objItem.Status WScript.Echo “StatusInfo: ” & objItem.StatusInfo WScript.Echo “SupportsDiskQuotas: ” & objItem.SupportsDiskQuotas WScript.Echo “SupportsFileBasedCompression: ” & objItem.SupportsFileBasedCompression WScript.Echo “SystemCreationClassName: ” & objItem.SystemCreationClassName WScript.Echo “SystemName: ” & objItem.SystemName WScript.Echo “VolumeName: ” & objItem.VolumeName WScript.Echo “VolumeSerialNumber: ” & objItem.VolumeSerialNumber Next

If you wanted to do the same thing in Windows PowerShell, the code would look like this:

That’s it for Quick-Hits Friday. This also draws to a close another week here on the Script Center. Looks like I will be spending the weekend working on designing games for the 2009 Summer Scripting Games. Our theme this year is the decathlon, so all the games will have that in common. If you want to stay up on all the details, follow us on Twitter. Have a fun weekend. I know mine is going to be a blast! See you on Monday.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

0 comments

Comments are closed. Login to edit/delete your existing comments