Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (04/24/09)
In This Post
|How Can I Script the Download of Large Binary Files?|
|How Do I Take Ownership of a File?|
|How Do I Get the Time on a Computer?|
|How Do I Increment a Number and Retain Its Format?|
|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! 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!
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! 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?
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:
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! I need a way to get the time on a computer.
The easiest way to get the time is to use the Now function that is built into VBScript. This is seen here:
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:
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! 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.
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 ‘ 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
How Can I Get a List of Mapped Drives from a Remote Machine?
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.
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:
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