Learn about Windows PowerShell
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.
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
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).
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:
'On Error Resume Next
strComputer = "."
wmiNS = "\root\cimv2"
wmiQuery = "win32_LocalTime=@"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & wmiNS)
Set objItem = objWMIService.get(wmiQuery)
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
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.
' This function pads a string with a padding character to create a new string
' of a defined length
' 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
' padded string
Function PadString(strInput, intReturnLength, strPadChar, blnPadAtEnd)
Do While NOT(len(strInput) >= intReturnLength)
If blnPadAtEnd = True Then
strInput = strInput & strPadChar
strInput = strPadChar & strInput
PadString = strInput
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
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
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
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