Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (1/29/10)
- How Can I Run This Windows PowerShell Command on a Remote Computer?
- Troubleshooting a Windows PowerShell Script for Active Directory
- Can I Detect the Title of the Command Prompt Window?
- How Can I Add Quotation Marks Around a String Variable?
How Can I Run This Windows PowerShell Command on a Remote Computer?
Hey, Scripting Guy!
I wanted to run the DU tool on several servers in my environment. Is there a way to script this request via Windows PowerShell? I can run it for one server by doing something like this.
PS> du -v “z:windows” | sort -Descending | Out-File c:du_test.txt
The Z: drive represents a mapping of the target server C: drive.
— JC
Hello JC,
Microsoft Scripting Guy Ed Wilson here. I would use Windows PowerShell 2.0 and remote the command. It is the easiest way to do this. You can download Windows PowerShell 2.0 for Windows Server 2008, Windows Vista, Windows XP, and Windows Server 2003. For Windows 7 and Windows Server 2008 R2, there is no need to download Windows PowerShell 2.0 because it is built into the operating system.
After you have installed Windows PowerShell 2.0, take a look at the about_Remoting articles in the online help. I access the help files by using the Get-Help cmdlet (help is an alias for that cmdlet), as seen here:
PS C:> help about_remote*
Name Category Synopsis
—- ——– ——–
about_remote HelpFile Describes how to run remote commands in Windows PowerShell.
about_remote_FAQ HelpFile Contains questions and answers about running remote commands
about_remote_jobs HelpFile Describes how to run background jobs on remote computers.
about_remote_output HelpFile Describes how to interpret and format the output of remote commands.
about_remote_requirements HelpFile Describes the system requirements and configuration requirements for
about_remote_troubleshooting HelpFile Describes how to troubleshoot remote operations in Windows PowerShell.
PS C:>
To run a command on a remote machine, you can use the Invoke-Command cmdlet, as shown here:
PS C:> Invoke-Command -ComputerName win7-pc -ScriptBlock { ipconfig }
Windows IP Configuration
Ethernet adapter Local Area Connection 2:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::dc70:f882:bda5:9133%17
IPv4 Address. . . . . . . . . . . : 192.168.1.110
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.254
Tunnel adapter isatap.{468C0E87-CED5-4D23-9F0E-C1B99C508131}:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Tunnel adapter Local Area Connection* 11:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
PS C:>
Executing against multiple machines is just as easy. If you have several computer names, you may want to place them into a text file that is readily accessible. This file needs to be accessible from the computer from where you launch the script—it does not need to be accessible on the target computers. A simple computers.txt file is seen in the following image.
By using the Get-Content cmdlet to read the contents of the text file to obtain the values for the –computername parameter, you can easily execute the command on a group of remote servers. This is seen here:
PS C:> Invoke-Command -ComputerName (Get-Content C:fsocomptuers.txt) -ScriptBlock {ipconfig}
Windows IP Configuration
Ethernet adapter Local Area Connection 2:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::dc70:f882:bda5:9133%17
IPv4 Address. . . . . . . . . . . : 192.168.1.110
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.254
Tunnel adapter isatap.{468C0E87-CED5-4D23-9F0E-C1B99C508131}:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Tunnel adapter Local Area Connection* 11:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Windows IP Configuration
Ethernet adapter Local Area Connection 3:
Connection-specific DNS Suffix . : nwtraders.com
Link-local IPv6 Address . . . . . : fe80::ec91:63e2:e2c9:3692%414
IPv4 Address. . . . . . . . . . . : 192.168.1.100
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.254
PS C:>
If for some reason you cannot upgrade to Windows PowerShell 2.0 at this time, your options will be somewhat limited. You may be able to use WMI and the create method from win32_process to run the remote command. The syntax is a bit nasty, as seen here:
([wmiclass]”\COMPUTERNAMErootcimv2:win32_process“).create(“PROCESSNAME”)
Troubleshooting a Windows PowerShell Script for Active Directory
Hey, Scripting Guy!
I’ve tried to use Windows Powershell 2.0’s Active Directory cmdlets to create a list of orphaned home drives as per the below; however, it seems that the Get-ADUser query always returns $null for all users with a samaccountname starting with 0-9 or A-F, even though doing a “Get-ADUser ‘username’ –Properties HomeDirectory” for one of those users returns a non-null value. Anyone with a samaccountname starting with G-Z returns the correct value; this happens whether it is run as part of this script or as one line against one of the accounts. Is there some quirk that I am unaware of or is there something seriously wrong with our domain? If it is relevant, our domain is 2008 Native with a mix of 2008 and 2008 R2 domain controllers, both RW and RO.
import-module ActiveDirectory
$path = “\pathtousers“
$file = New-Item -type file “C:unusedhome.txt”
$homedrives = Get-ChildItem $path
ForEach($folder in $homedrives){
$name = $path + $folder.name
$user = Get-ADUser -Filter { HomeDirectory -eq $name }
if($user -eq $null){
add-content $file $name
}
$user = $null
}
Many thanks.
— AB
Hello AB,
Microsoft MVP Brandon answered this one. He said, “Try this, it works for me” about this script, which he wrote:
import-module ActiveDirectory
$path = “C:dataHomeFolder”
$file = New-Item -type file “C:dataunusedhome.txt” -Force
$homedrives = Get-ChildItem $path
foreach($folder in $homedrives)
{
$user = Get-ADUser $Folder.Name -properties HomeDirectory
Write-Host “Found User: $User”
if($user.homedirectory -ne $folder.FullName){$folder.FullName | add-content $file.FullName}
$user = $null
}
<
p style=”MARGIN: 0in 0in 8pt” class=”MsoNormal”>
Can I Detect the Title of the Command Prompt Window?
Hey, Scripting Guy!
I want to detect the command prompt window title. I need to be able to determine if the user is running in an elevated/admin prompt or not. The window title for a “normal” Command Prompt windows says, “Command Prompt,” but the window title for an admin Command Prompt windows says, “Administrator: Command Prompt.”
If I store the title so I can compare against the two window titles above, I can determine if I am just in a normal shell or an elevated shell and then take actions based on where the user is. I was hoping to use ordinary command-prompt utilities, but I do know VBScript, I have not looked very deep into Windows PowerShell yet.
However, you could restate the task as “determining if a user is in an elevated prompt.” It does not matter to me if the window title is used to figure that out. It is just the only way I can see at the moment that they are different. If there is, another way to do this is okay, too.
Hope you can help.
— KW
Hello KW,
Take a look at this script. It uses Windows PowerShell 2.0 (required for the Try…Catch bit).
Test-CmdPromptAdmin.ps1
# ——————————————————————–
# Test-CmdPromptAdmin.ps1
# ed wilson, msft, 12/22/2009
#
# Checks to see if the cmd prompt is elevated.
# If no cmd prompt then script exits.
#
# ——————————————————————–
Function Test-CmdPromptAdmin
{
$errorActionPreference = “stop”
Try
{
$windowTitle = (get-Process -Name cmd).MainWindowTitle
if($windowTitle -match “administrator”)
{ $true }
else { $false }
}
Catch [System.Exception]
{ exit }
} #end function Test-CmdPromptAdmin
# *** Entry point to script ***
If(Test-CmdPromptAdmin)
{ “The cmd prompt is elevated”}
If(-not (Test-CmdPromptAdmin))
{ “The cmd prompt is not elevated” }
How Can I Add Quotation Marks Around a String Variable?
Hey, Scripting Guy!
Hey, Scripting Guy! I would like to add quotation marks around a string variable. However, for whatever reason, the first quotation mark is fine but the second quotation mark goes to the next line. Any ideas about how to fix this? Here is all I am doing:
PS C:> $test='”‘+”$strname”+'”‘
PS C:> $test
“\?Volume{747b409b-b755-11de-ab54-0025b3a915b7}
“
As you can see, the second quotation mark is not where I want it to be. I want it to be after the last “”.
— OC
Hello OC,
My guess is that it is exceeding your screen width. The script should still run fine.
In the Windows PowerShell console, you can increase the screen width by clicking the Windows Powershell icon in the upper left corner, clicking Properties, and then clicking Layout. The width is by default set to 80; I generally set mine to 120. This is seen in the following image.
Well, this concludes another edition of Quick-Hits Friday. It also concludes another exciting week on the Script Center. Join us next week as we delve into the mysteries
0 comments