Select-Object - what can I select? - powershell

I'm learning PowerShell and I am stuck at an issue where I have to export something and I don't know its object name.
I use this command:
Get-Mailbox -ResultSize Unlimited | Select-Object DisplayName,PrimarySmtpAddress
How do I find out what objects I can select with Select-Object?

Use Get-Member.
Get-Mailbox -ResultSize Unlimited | Get-Member
will show you all of the properties (as well as methods and events).

Get-member will show you all of the properties and methods of an object, but it doesn't show you the values. To see the values, I recommend using Format-List instead.
For example, Get-ChildItem (Dir) shows you a list of files, but also provides a tremendous amount of other properties we might want. To see them all, pipe it into format-list.
PS C:\temp\NewFolder> dir
Directory: C:\temp\NewFolder
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 7/22/2015 11:31 AM 44 Computers.txt
-a---- 7/22/2015 12:37 PM 106 NotepadProfile.ps1
-a---- 7/22/2015 11:07 AM 21 Tester.txt
Not bad, and a pretty useful listing, but to see everything we have to work with, throwing Format-List (FL) is the way to go.
PS C:\temp\NewFolder> dir | format-list *
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\temp\NewFolder\Computers.txt
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\temp\NewFolder
PSChildName : Computers.txt
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
VersionInfo : File: C:\temp\NewFolder\Computers.txt
InternalName:
OriginalFilename:
FileVersion:
FileDescription:
Product:
ProductVersion:
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language:
BaseName : Computers
Target :
LinkType :
Mode : -a----
Name : Computers.txt
Length : 44
DirectoryName : C:\temp\NewFolder
Directory : C:\temp\NewFolder
IsReadOnly : False
Exists : True
FullName : C:\temp\NewFolder\Computers.txt
Extension : .txt
CreationTime : 7/22/2015 11:13:40 AM
CreationTimeUtc : 7/22/2015 3:13:40 PM
LastAccessTime : 7/22/2015 11:13:40 AM
LastAccessTimeUtc : 7/22/2015 3:13:40 PM
LastWriteTime : 7/22/2015 11:31:33 AM
LastWriteTimeUtc : 7/22/2015 3:31:33 PM
Attributes : Archive

Related

How do I open a folder link in powershell/windows terminal?

When I type the obvious thing
PS > cd folderName.lnk
or
PS > cd folderName.lnk
in both cases it claims that the file doesn't exist, even though 'ls' shows that it does. Any suggestions? Thank you
try this:
$sh = New-Object -ComObject WScript.Shell
$target = $sh.CreateShortcut('<full-path-to-shortcut>').TargetPath
set-location -LiteralPath $target
make sure you use the full path to the shortcut, not a relative path like .\FolderName.lnk
you can also script it so you always get the absolute path:
$shortcut = '.\Shortcut.lnk'
$absolutepath = Convert-Path -Path $shortcut
$sh = New-Object -ComObject WScript.Shell
$target = $sh.CreateShortcut($absolutepath).TargetPath
Set-Location -LiteralPath $target
As noted by others, .lnk files are not directories,...
Get-ChildItem -Path "$env:USERPROFILE\Desktop"
# Results
<#
Directory: C:\Users\WDAGUtilityAccount\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/2/2023 1:39 PM 737 Scripts.lnk
#>
...so you cannot directly navigate to them with any directory-like command.
The Desktop is the folder for that file.
(Get-ChildItem -Path "$env:USERPROFILE\Desktop").Fullname
# Results
<#
C:\Users\WDAGUtilityAccount\Desktop\Scripts.lnk
#>
Get-ChildItem -Path "$env:USERPROFILE\Desktop" |
Select-Object -Property '*'
# Results
<#
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\WDAGUtilityAccount\Desktop\Scripts.lnk
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\WDAGUtilityAccount\Desktop
PSChildName : Scripts.lnk
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
Mode : -a----
VersionInfo : File: C:\Users\WDAGUtilityAccount\Desktop\Scripts.lnk
InternalName:
OriginalFilename:
FileVersion:
FileDescription:
Product:
ProductVersion:
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language:
BaseName : Scripts
Target : {}
LinkType :
Name : Scripts.lnk
Length : 737
DirectoryName : C:\Users\WDAGUtilityAccount\Desktop
Directory : C:\Users\WDAGUtilityAccount\Desktop
IsReadOnly : False
Exists : True
FullName : C:\Users\WDAGUtilityAccount\Desktop\Scripts.lnk
Extension : .lnk
CreationTime : 1/2/2023 1:39:41 PM
CreationTimeUtc : 1/2/2023 9:39:41 PM
LastAccessTime : 1/2/2023 1:39:43 PM
LastAccessTimeUtc : 1/2/2023 9:39:43 PM
LastWriteTime : 1/2/2023 1:39:41 PM
LastWriteTimeUtc : 1/2/2023 9:39:41 PM
Attributes : Archive
#>
So, you have to extract that FQDN from the link and use the available directory/Name commands to navigate to that path.

Get Drive letter from Volume ID

I want to use drive letter instead of Volume ID like below. How can I do that ?
Thanks,
My output :
VolumeName OriginatingMachine InstallDate
\\?\Volume{3c0a6eed-1b4c-4e90-a25b-8af1af46e368}\ app01.contoso.com 4/13/2021 6:03:34 PM
\\?\Volume{de5c18ac-56e1-4efa-afb4-abaf476a99a9}\ app01.contoso.com 4/13/2021 6:03:34 PM
My desired output :
VolumeName OriginatingMachine InstallDate
E: app01.contoso.com 4/13/2021 6:03:34 PM
X: app01.contoso.com 4/13/2021 6:03:34 PM
Command:
Get-CimInstance Win32_ShadowCopy | Where InstallDate -lt ([datetime]::Now.AddDays(-5)) | Select-Object VolumeName,OriginatingMachine,InstallDate
Get-CimInstance Win32_ShadowCopy output :
Caption :
Description :
InstallDate : 9/17/2021 9:22:06 PM
Name :
Status :
ClientAccessible : False
Count : 11
DeviceObject : \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1234
Differential : True
ExposedLocally : False
ExposedName :
ExposedPath :
ExposedRemotely : False
HardwareAssisted : False
ID : {3C8DAB36-F083-4C68-84BA-E339B8A18AF3}
Imported : False
NoAutoRelease : True
NotSurfaced : False
NoWriters : False
OriginatingMachine : app01.contoso.com
Persistent : True
Plex : False
ProviderID : {B5946137-7B9F-4925-AF80-51ABD60B20D5}
ServiceMachine : app01.contoso.com
SetID : {D3D15CE2-9FFC-4A22-B03C-77D7FCB7D40E}
State : 12
Transportable : False
VolumeName : \\?\Volume{85e62cfa-2e9c-4a46-af5a-f0748acd60b6}\
PSComputerName :
The Win32_ShadowCopy command returns Win32_ShadowCopy objects, which have a number of fields all described here.
Some of the fields provided in ShadowCopy happen to match other WMI Classes which have info about Drive Letters, namely the VolumeName field. This field happens to also be present on both the ShadowCopy and Win32_Volume class, the latter of which has the drive letter property we need!
All we have to do is lookup all of the shadow copies, then lookup all of the volumes on the machine, then we can loop through the copies to find the matching volumes. If you have some really complex mounting logic, you'll need to add some extra logic though in the foreach section.
So we would make a quick little function to do this lookup for us, which would look like this:
function Get-Win32ShadowVolumeDiskInfo{
$shadowCopies = Get-CimInstance Win32_ShadowCopy
$volumes = Get-CimInstance Win32_Volume
$returnObject = #()
foreach ($copy in $shadowCopies){
$matchingVolume = $volumes | Where DeviceID -eq $copy.VolumeName
$returnObject += [PSCustomObject]#{
VolumeName=$matchingVolume.Name;
OriginatingMachine = $copy.OriginatingMachine;
InstallDate = $copy.InstallDate}
}
$returnObject
}

How to find the title for a PDF from the metadata?

How can I get the title for a PDF file after having renamed the file itself?
PSPath : Microsoft.PowerShell.Core\FileSystem::/home/nicholas/to/99.pdf
PSParentPath : Microsoft.PowerShell.Core\FileSystem::/home/nicholas/to
PSChildName : 99.pdf
PSDrive : /
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
Mode : -----
ModeWithoutHardLink : -----
VersionInfo : File: /home/nicholas/to/99.pdf
InternalName:
OriginalFilename:
FileVersion:
FileDescription:
Product:
ProductVersion:
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language:
BaseName : 99
Target :
LinkType :
Length : 592483
DirectoryName : /home/nicholas/to
Directory : /home/nicholas/to
IsReadOnly : False
FullName : /home/nicholas/to/99.pdf
Extension : .pdf
Name : 99.pdf
Exists : True
CreationTime : 2/19/2021 11:45:18 PM
CreationTimeUtc : 2/20/2021 7:45:18 AM
LastAccessTime : 2/20/2021 2:02:36 AM
LastAccessTimeUtc : 2/20/2021 10:02:36 AM
LastWriteTime : 2/19/2021 11:45:18 PM
LastWriteTimeUtc : 2/20/2021 7:45:18 AM
Attributes : Normal
PS /home/nicholas/to>
PS /home/nicholas/to> Get-ChildItem -Path ./ –File | Select-Object -Property *
This is to bulk import PDF files into calibre, which, notably, seems to recognize duplicates and even displays some titles. Is it parsing the PDF file itself, or gleaning this from meta-data?
For this, you can use pdfinfo.exe which you can find as part of the free Xpdf command line tools.
After you have downloaded and extracted the zip file, copy pdfinfo.exe to some directory and make sure you unblock it, either by right-click or by using PowerShell
Unblock-File -Path 'Where\Ever\You\Have\Copied\It\To\pdfinfo.exe'
Using that, to get the original title as stored in the pdf, you do
$title = ((& 'D:\Test\pdfinfo.exe' 'D:\Test\test.pdf' |
Where-Object { $_ -match '^Title:' }) -split ':', 2)[-1].Trim()

In PowerShell why does "casting" to FileInfo set the wrong FullName, Directory, and DirectoryName

I'm noticing a VERY odd behavior in both my PS ISE and PS when I'm getting a FileInfo object by calling
$FileInfo = [System.IO.FileInfo](".\SomeFile.ext")
When I look at its properties the DirectoryName and its related properties all default to the ORIGINAL path that PS opens in.
Here's a copy from my ISE which launches as an administrator with c:\Windows\System32 as the default path
If I run the following code:
$Fileinfo = [System.IO.FileInfo](".\#OpenWithToastLogo.png")
cd c:\temp
$Fileinfo2 = [System.IO.FileInfo](".\activation.txt")
z:
$Fileinfo3 = [System.IO.FileInfo](".\7za.exe")
$Fileinfo | fl *
$Fileinfo2 | fl *
$Fileinfo3 | fl *
I get
VersionInfo :
File : C:\WINDOWS\system32\#OpenWithToastLogo.png
InternalName :
OriginalFilename :
FileVersion :
FileDescription :
Product :
ProductVersion :
Debug : False
Patched : False
PreRelease : False
PrivateBuild : False
SpecialBuild : False
Language :
BaseName : #OpenWithToastLogo
Target : {C:\Windows\WinSxS\wow64_microsoft-windows-openwith_31bf3856ad364e35_10.0.10240.16384_none_7f75eaad41c1f239\#OpenWithToastLogo.png,C:\Windows\SysWOW64\#OpenWithToastLogo.png}
LinkType : HardLink
Mode : -a---l
Name : #OpenWithToastLogo.png
Length : 160
DirectoryName : C:\WINDOWS\system32
Directory : C:\WINDOWS\system32
IsReadOnly : False
Exists : True
FullName : C:\WINDOWS\system32\#OpenWithToastLogo.png
Extension : .png
CreationTime : 7/10/2015 7:00:32 AM
CreationTimeUtc : 7/10/2015 11:00:32 AM
LastAccessTime : 7/10/2015 7:00:32 AM
LastAccessTimeUtc : 7/10/2015 11:00:32 AM
LastWriteTime : 7/10/2015 7:00:32 AM
LastWriteTimeUtc : 7/10/2015 11:00:32 AM
Attributes : Archive
VersionInfo :
BaseName : activation
Target :
LinkType :
Mode : darhsl
Name : activation.txt
Length :
DirectoryName : C:\WINDOWS\system32
Directory : C:\WINDOWS\system32
IsReadOnly : True
Exists : False
FullName : C:\WINDOWS\system32\activation.txt
Extension : .txt
CreationTime : 12/31/1600 7:00:00 PM
CreationTimeUtc : 1/1/1601 12:00:00 AM
LastAccessTime : 12/31/1600 7:00:00 PM
LastAccessTimeUtc : 1/1/1601 12:00:00 AM
LastWriteTime : 12/31/1600 7:00:00 PM
LastWriteTimeUtc : 1/1/1601 12:00:00 AM
Attributes : -1
VersionInfo :
BaseName :
7za Target :
LinkType :
Mode : darhsl
Name : 7za.exe
Length :
DirectoryName : C:\WINDOWS\system32
Directory : C:\WINDOWS\system32
IsReadOnly : True
Exists : False
FullName : C:\WINDOWS\system32\7za.exe
Extension : .exe
CreationTime : 12/31/1600 7:00:00 PM
CreationTimeUtc : 1/1/1601 12:00:00 AM
LastAccessTime : 12/31/1600 7:00:00 PM
LastAccessTimeUtc : 1/1/1601 12:00:00 AM
LastWriteTime : 12/31/1600 7:00:00 PM
LastWriteTimeUtc : 1/1/1601 12:00:00 AM
Attributes : -1
With my regular account it defaults to my H:\ path so the same test would have H:\ as the DirectoryName.
And yes, each of these files ONLY exists in the directory it was relative to.
Has anyone seen this before, and do they know a good fix? Using fully qualified of course works but this is for a script that other technicians might run and we're all pretty used to the idea of using relative pathing with PS.
PowerShell has a notion of your current location. You can see this
using the $pwd automatic variable or the Get-Location cmdlet [..]
This path is used by PowerShell to resolve relative paths at the level of
the PowerShell API.
[..]
Applications have a notion of the current directory. This is the
directory used to resolve relative paths at the level of the Windows
API.
How you Get Burned
Your current location may or may not be the same as your current directory.
From http://www.beefycode.com/post/The-Difference-between-your-Current-Directory-and-your-Current-Location.aspx
and
One question that comes up frequently is, “Why does PowerShell not
change its [System.Environment]::CurrentDirectory as I navigate around
the shell?”
One of the difficult aspects of this comes from the fact that
PowerShell supports multiple pipelines of execution. Although it’s
not directly exposed yet, users will soon be able to suspend jobs to
the background, and other concurrent tasks.
The current directory affects the entire process, so if we change the
directory as you navigate around the shell, you risk corrupting the
environment of jobs you have running in the background.
When you use filenames in .Net methods, the best practice is to use
fully-qualified path names. The Resolve-Path cmdlet makes this easy:
$reader = new-object System.Xml.XmlTextReader (Resolve-Path baseline.xml)
From http://www.leeholmes.com/blog/2006/07/18/set-location-and-environmentcurrentdirectory/

Why does PowerShell output change after loading assembly?

I am getting some unusual output from New-Item in a script if I've first loaded an assembly with reflection. Why?
If I run
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")
New-Item -Path "temp" -ItemType directory
I get the following odd output from New-Item:
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\swoogan\Desktop\temp
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\swoogan\Desktop
PSChildName : temp
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : True
Name : temp
Parent : Desktop
Exists : True
Root : C:\
FullName : C:\Users\swoogan\Desktop\temp
Extension :
CreationTime : 7/28/2014 11:03:10 AM
CreationTimeUtc : 7/28/2014 3:03:10 PM
LastAccessTime : 7/28/2014 11:03:10 AM
LastAccessTimeUtc : 7/28/2014 3:03:10 PM
LastWriteTime : 7/28/2014 11:03:10 AM
LastWriteTimeUtc : 7/28/2014 3:03:10 PM
Attributes : Directory
BaseName : temp
Mode : d----
The output I am expecting is:
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 7/28/2014 11:03 AM temp
If I pipe the output of LoadWithPartialName to Out-Null, then I do get the expected output. I would like to understand what is happening here so I can anticipate these discrepancies in the future.
I think I figured this out.
In the original case with the LoadWithPartialName, the output of the script is an array of PSObject since Powershell sends any unhandled object to the pipeline, and the items are of mixed types (0 = AssemblyInfo from Load; 1 = DirectoryInfo from new-item).
If you redirect the LoadWithPartialName to [void] or even save the output in a variable, the output of the script is a single DirectoryInfo object.
PSObject gets formatted differently than DirectoryInfo