PowerTip of the Day, from PowerShell.com:
Try this one-liner if you need to print out all PDF documents you have stored in one folder:
Dirc:\myfolder\*.pdf|Foreach-Object { Start-Process-FilePath$_.FullName – VerbPrint }
Try this one-liner if you need to print out all PDF documents you have stored in one folder:
Dirc:\myfolder\*.pdf|Foreach-Object { Start-Process-FilePath$_.FullName – VerbPrint }
When you read multivalued information from WMI or any other source, for example, network adapter IP addresses, this information is returned as a multiline string:
PS> Get-WmiObject-ClassWin32_NetworkAdapterConfiguration-Filter‘IPEnabled=true’|Select-Object-ExpandPropertyIPAddress
78.64.118.150
fe80::ad62:ac4d:4dea:936d
If you want to turn this into a list, use the operator -join:
PS> (Get-WmiObject-ClassWin32_NetworkAdapterConfiguration-Filter‘IPEnabled=true’|Select-Object-ExpandPropertyIPAddress) -join‘, ‘
78.64.118.150, fe80::ad62:ac4d:4dea:936d
It expects the multiline (array) data on its left side and the delimiter you want to use to separate the values on its right side.
When you query network adapters with WMI, it is not easy to find the active network card. To find the network card(s) that are currently connected to the network, you can filter based on NetConnectionStatus which needs to be “2″ for connected cards. Then you can take the MAC information from the Win32_NetworkAdapter class and the IP address from the Win32_NetworkAdapterConfiguration class and combine both into one custom return object:
PS> Get-WmiObjectWin32_NetworkAdapter-Filter‘NetConnectionStatus=2′
ServiceName : NETw5s64
MACAddress : 00:22:FA:D9:E1:50
AdapterType : Ethernet 802.3
DeviceID : 11
Name : Intel(R) WiFiLink 5100 AGN
NetworkAddresses :
Speed : 54000000
This gets you the network hardware but not the network configuration. To get the configuration data for this network card (like its IP address), get the related Win32_NetworkAdapterConfiguration instance:
functionGet-NetworkConfig {
Get-WmiObjectWin32_NetworkAdapter-Filter‘NetConnectionStatus=2′|
ForEach-Object {
$result= 1 |Select-ObjectName, IP, MAC
$result.Name=$_.Name
$result.MAC=$_.MacAddress
$config=$_.GetRelated(‘Win32_NetworkAdapterConfiguration’)
$result.IP=$config|Select-Object-expandIPAddress
$result
}
}
PS> Get-NetworkConfig
Name IP Mac
—- – —
Intel(R) WiFiLink 5100… {78.64.118.150, fe80::a… 00:22:FA:D9:E1:50
Provided you have Microsoft Excel installed, here is a clever function that you can use to convert PowerShell results into Excel spreadsheets:
functionOut-ReportExcel {
param(
$Path=“$env:temp\report$(Get-Date -format yyyyMMddHHmmss).csv“,
[switch]$Open
)
$Input|
Export-Csv$Path-NoTypeInformation-UseCulture-EncodingUTF8
if($Open) { Invoke-Item$Path }
}
Simply try it:
When you access Microsoft Excel from script, you may have noticed that it never gets removed from memory again, even if you call its Quit() method:
‘Excel processes: {0}’-f @(Get-Processexcel-ea 0).Count
$excel=New-Object-ComObjectExcel.Application
$excel.Visible=$True
Start-Sleep 5
$excel.Quit()
‘Excel processes: {0}’-f @(Get-Processexcel-ea 0).Count
Now you could try and kill that orphaned process:
Stop-Process-nameexcel
However, you now would kill all open Excel instances, not just the one you launched from script. Also, killing a process with Stop-Process is hostile, and Excel may complain the next time you launch it that it was shut down unexpectedly.
Here is how you tell the .NET Framework to quit Excel peacefully:
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
Start-Sleep 1
‘Excel processes: {0}’-f @(Get-Processexcel-ea 0).Count
When you use Dir (alias: Get-ChildItem) to list folder contents, you can use simple wildcards but they do not give you much control. A much more powerful approach is to use regular expressions. Since Get-ChildItem does not support regular expressions, you can use Where-Object to filter the results returned by Dir. This line will get you any file with a number in its filename, ignoring numbers in the file extension:
dir$home-Recurse|Where-Object {$_.Name-match‘\d.*?\.’}
You can use the env: PowerShell drive to list all Windows environment variables like this:
dir env:
Since PowerShell supports wildcards, you can easily limit the output to environment variables with a certain keyword:
PS> Direnv:*user*
Name Value
—- —–
USERNAME w7-pc9
USERPROFILE C:\Users\w7-pc9
ALLUSERSPROFILE C:\ProgramData
USERDOMAIN DEMO5
To access the content of an individual environment variable, use the variable syntax like this:
“Username: $env:username”
And if you want to list environments with a keyword in its value, use Where-Object. This will list all environment variables with a “program” keyword in its value:
PS> direnv: |Where-Object { $_.Value-like‘*Program*’ }
Name Value
—- —–
ALLUSERSPROFILE C:\ProgramData
CLASSPATH .;C:\ProgramFiles (x86)\QuickTime\QTSystem\Q…
CommonProgramFiles C:\ProgramFiles\CommonFiles
CommonProgramFiles(x86) C:\ProgramFiles (x86)\CommonFiles
CommonProgramW6432 C:\ProgramFiles\CommonFiles
…
PowerShell is console based, so its default menus are console based as well. To offer choices to your users, here is some sample code to create a simple menu:
$title=“Reboot System Now”
$message=“Do you want to reboot your machine now?”
$yes=New-ObjectSystem.Management.Automation.Host.ChoiceDescription“&Yes”, `
“Reboots the system now.”
$no=New-ObjectSystem.Management.Automation.Host.ChoiceDescription“&No”, `
“Does not reboot the system. You will have to reboot manually later.”
$options= [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result=$Host.ui.PromptForChoice($title, $message, $options, 0)
switch ($result)
{
0 {“You selected Yes.”
Restart-Computer-whatif
}
1 {“You selected No.”}
}
And this is what the output would look like:
RebootSystemNow
doyouwanttorebootyourmachinenow?
[Y] Yes [N] No [?] Help (defaultis“Y”): ?
Y-Rebootsthesystemnow.
N-Doesnotrebootthesystem. Youwillhavetorebootmanuallylater.
[Y] Yes [N] No [?] Help (defaultis“Y”): y
YouselectedYes.
Whatif: Performingoperation“Restart-Computer”onTarget“localhost (DEMO5)”.
If a script needs to run only particular commands with full Administrator privileges, you can run those in a separate elevated shell.
$code = “md $env:windir\newfolder | Out-Null”
if ((Test-Path $env:windir\newfolder) -eq $false) {
Start-Process powershell.exe -Verb RunAs -ArgumentList “-noprofile -windowstyle hidden -command $code”
}
if ((Test-Path $env:windir\newfolder) -eq $false) {
‘Folder still does not exist, something went wrong’
} else {
‘Folder was created with admin privileges’
}
PowerTip of the Day, from PowerShell.com: |
Listing Windows UpdatesThere is a not widely known COM object that you can use to list all the $Session = New-Object -ComObject Microsoft.Update.Session |