Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (3/12/10)

Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (3/12/10)

  • Comments 4
  • Likes

Bookmark and Share

In this post:

 

How Can I Format Dates in Windows PowerShell?

Hey, Scripting Guy! Question

Hey, Scripting Guy! I am having trouble formatting a date in Windows PowerShell. I would like to format the date as seen here:

(Get-Date).AddDays(-1) | $_.ToString("yyyy-MM-dd")

However, I am getting an error when I run that command. The only way I found to format the date uses three lines of code as seen here:


$p= (Get-Date).AddDays(-1)
$p= $p.ToString("yyyy-MM-dd")
$p


Is there a way to have two lines of code instead three?


-- SA

 

Hey, Scripting Guy! AnswerHello SA,

Microsoft Scripting Guy Ed Wilson here. Yes, you could do it in two lines, but you can also do it in one line of code. Here it is in one line:

PS C:\> ((Get-Date).AddDays(-1)).ToString("yyyy-MM-dd")

2010-02-28

The thing to keep in mind is that once you specify the format of the date, you no longer have a dateTime objectyou have a string. This is seen here:

PS C:\> (Get-Date -Format "yyyy-MM-dd").AddDays(-1)

Method invocation failed because [System.String] doesn't contain a method named 'AddDays'.

At line:1 char:40

+ (Get-Date -Format "yyyy-MM-dd").AddDays <<<< (-1)

    + CategoryInfo          : InvalidOperation: (AddDays:String) [], RuntimeException

    + FullyQualifiedErrorId : MethodNotFound

As the error tells us, a system.string does not have an AddDays method. Therefore, the expression inside the first set of parentheses returns a string, and not a dateTime object. The cool thing is that when using the ToString method, we are allowed to specify the format we wish to retrieve. Therefore, we use the AddDays method from the dateTime object to get yesterday’s date, and then we group that with a set of parentheses, and call the ToString method.

 


A Get-ProgID Function from James Brundage

Hey, Scripting Guy! Question

Hey, Scripting Guy! This question is about COM objects. I thought this might be useful. James Brundage posted a Get-ProgID function on the Windows PowerShell team blog that was pretty cool. You can use it in this manner.

Get-ProgID| ?{$_.progid -match "application"} | sort

 

-- DF

 

Hey, Scripting Guy! AnswerHello DF,

Thanks for the additional information. You are right. James writes some really cool stuff. 


 

How Can I Run This Script on Remote Computers?

Hey, Scripting Guy! Question

Hey, Scripting Guy! Simple question. Your script in the How Can I Retrieve a List of System DSNs on a Computer? post works terrific on the local workstation (to get the system DSNs). What is the best way to run it on remote workstations? I have a list of about 100 workstations where I need to get this information. How would you recommend changing the script to run on many workstations?

-- MB

 

Hey, Scripting Guy! AnswerHello MB,

The script should work on a remote computer. You will need to change the value of the strComputer variable from a period to the name of your remote computer. This is seen here:

 

Const HKEY_LOCAL_MACHINE = &H80000002

 

strComputer = "RemoteComputer"

 

Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")

 

strKeyPath = "SOFTWARE\ODBC\ODBC.INI\ODBC DATA SOURCES"

 

objRegistry.EnumValues HKEY_LOCAL_MACHINE, strKeyPath, arrValueNames, arrValueTypes

 

For i = 0 to Ubound(arrValueNames)

    strValueName = arrValueNames(i)

    objRegistry.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strValue   

    Wscript.Echo strValueName & " -- " & strValue

Next

 

Because you want to run this against 100 remote machines, you do not want to have to edit the script 100 times. Therefore, you should place the 100 computer names in a text file. Better yet, use VBScript to query for the computer names stored in a particular organization unit (OU) in Active Directory. At any rate, you would then use a For...Each...Next loop to walk through the contents of the file or the collection of computer names returned from Active Directory to perform your query. You could also use a Do...Until loop. There are some good scripting templates on the Scripting Guys Script Repository that will help you get started. One template uses a text file, and another queries Active Directory for a list of computers in an OU.

There are more than 150 such VBScript templates in the Script Repository that all have various combinations of features.

 

Using Command-Line Arguments with Batch Files 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I have a one-line batch file that runs a Windows PowerShell command to get the running processes on a remote server and then writes the results to a text file. Is there a way that I could prompt for the server name instead of manually editing the file each time I run it against a different server? In the past, I have used input boxes in VBScript, but I cannot seem to make it work with Windows PowerShell. This is my batch file:

powershell.exe -command tasklist /S \\server1 > C:\output\server1.txt

 

-- MO

 

Hey, Scripting Guy! AnswerHello MO,

Because you are using a batch file, you need to modify the file to accept command-line arguments. Command-line arguments are input via parameters in batch files. When a command is read from a batch file, the shell replaces parameters in the command text with the corresponding argument. Parameters in the file are preceded with a percent sign: %0, %1, %2, etc., in the order in which they are supplied. Keep in mind that %0 is actually the name of the script file itself. The first parameter, therefore, is %1. In your batch file, use %1 for your server name and supply the name of the server from the command line when you call the batch file. If it were I, however, I would simply use Windows PowerShell remoting, and not mess around with batch files. But perhaps that is just me.

 

Can You Help Me Improve My Script?

Hey, Scripting Guy! Question

Hey, Scripting Guy! I have a problem: I have to list all the files of a specific folder (including subfolders), and get the respective MD5 for each file. My code runs but for around 3,000 files it runs in 5 hours. Please help me to improve my script. My code is posted in the Script Repository.

-- EG

 

Hey, Scripting Guy! AnswerHello EG,

Awesome script! If it does 3,000 files in 5 hours, that is 600 files an hour and 10 files each minute,  which is pretty good performance from an uncompiled, interpreted script. To be honest, your script is rather long and complicated, and it would take me a significant amount of time and testing to obtain even marginal performance improvements. I have seen where you are creating some objects twice, and by reusing your objects, you gain some improvement. However, VBScript is generally pretty quick in creating objects, so the improvement would be negligible. But in the end, we would only be putting racing stripes on a dinosaur.

You would be much better off writing this in C++, or better yet, simply finding an MD5 utility on the Internet. There are dozens out there that I know of.

Note: I also suggest that you post this to the Scripting Guy’s Forum in case someone else had a different or better approach. Here is the link to that discussion, which is seen in the following image.

Image of forum thread about this script

 

Well, this concludes another super exciting edition of Quick-Hits Friday. It also concludes another super exciting week on the Script Center. Join us tomorrow for Weekend Scripter as we delve into the mysteries of…well, we will let that remain a mystery for now.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Scripting Guy,

    I am trying to find some PowerShell script to chage the default location of IIS 7.5 log files. I am planning to run this script on IIS 7.5 on a Core W2k8 R2. Would be grateful for an example.

    Thanks in advance.

  • I am currently swamped with getting the games organized for the 2010 Scripting Games and do not think I can get to your question anytime soon. So I would suggest you post your question on the Official Scripting Guys Forum where there are several people available to help. http://social.technet.microsoft.com/Forums/en/ITCG/threads?page=1&lc=1033

    Thanks Ed

  • PS C:\> (Get-Date -Format "yyyy-MM-dd").AddDays(-1)

    Method invocation failed because [System.String] doesn't contain a method named 'AddDays'.

    At line:1 char:40

    + (Get-Date -Format "yyyy-MM-dd").AddDays <>

    + CategoryInfo : InvalidOperation: (AddDays:String) [], RuntimeException

    + FullyQualifiedErrorId : MethodNotFound

    According to this error, finally i found a solution:

    Code: Get-date $([datetime]::Now).AddDays(-7) -Format 'yyyy-MM-dd'

  • (Get-Date).AddDays(-1).ToString("yyyy-MM-dd")