How to find the drive letter of a newly inserted USB drive using Powershell? - windows

I am trying to accomplish this:
When I insert a USB drive in Windows (Win7 and Win8), I want a script to be started (Powershell or batch command) automatically. The machine has autoplay disabled.
I setup a scheduled task with event id 2010 in DriveFrameworks-UserMode as trigger. The scheduled task works. However, I am having difficulties finding the drive letter of the newly inserted USB drive.
I found a few solutions on the Internet, but they didn't fit my requirements. The solutions either check for all drive letters (A to Z), or check for USB drive. I would like to correlate the drive letter that is associated with the event in the DriveFrameworks-UserMode trigger.
This post (How do i get the drive letter of a USB Drive in Powershell?) gave me some hints and I checked classes win32_logicaldisk, win32_diskdrive, and win32_pnpentity, but I couldn't find a clue matching them.
Any help is appreciated.

This should help:
$diskdrive = gwmi win32_diskdrive | ?{$_.interfacetype -eq "USB"}
$letters = $diskdrive | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_. deviceid}
$drive = gwmi win32_volume | ? {$letters -contains ($_.name -replace "\\")}
$drive.DriveLetter
PS. There is a similar discussion here

Related

How to get Bluetooth device battery percentage using PowerShell on windows?

I am trying to plot a graph for Bluetooth headphone battery discharge. For that I need to read battery percentage of the connected device. I can see power information is available on GUI for the device. Is there any way to get the battery percentage info for connected Bluetooth device using PowerShell? (like using wmi or anything else)
In my findings, you can get information on Bluetooth devices using the Get-PnpDevice cmdlet. This should return a list of PnP Devices, their Status, Class, FriendlyName and InstanceID.
Get-PnpDevice
You can filter the results with -Class parameter. To specify Bluetooth PnP devices, you can enter "Bluetooth" as a string value for the -Class parameter.
Get-PnpDevice -Class 'Bluetooth'
You can then specify the device you have in mind from this list by their FriendlyName using the -FriendlyName parameter and enter the desired device's FriendlyName as a string value for the parameter.
Get-PnpDevice -Class 'Bluetooth' -FriendlyName 'Device FriendlyName'
Note: You can also specify the device using the -InstanceId parameter and providing the device's InstanceId as a string value for the parameter.
If you then pipe the previous command to the Get-PnpDeviceProperty cmdlet, it will return a list of the device's properties, including its InstanceId, KeyName, Type and Data.
Get-PnpDevice -Class 'Bluetooth' -FriendlyName 'Device FriendlyName' |
Get-PnpDeviceProperty
Beyond this point, I was able to further filter the results of the command by using the -KeyName parameter and entering the KeyName of the property that (I assume) contains Device Power Data as a string value for the parameter.
Get-PnpDevice -Class 'Bluetooth' -FriendlyName 'Device FriendlyName' |
Get-PnpDeviceProperty -KeyName 'PropertyKeyName'
Unfortunately this is as far as I've gotten to solving the problem. Hopefully my contribution helps.
As far as I am aware, there is no way to poll bluetooth device data beyond what you would get with Get-WmiObject, since the battery status seen in Windows Settings -> Bluetooth Devices is something coming from the vendors/devices driver and seems to, as of now, be inaccessible by PowerShell, unless there is some exotic snapin I am not aware of.
You can get all possible device information via this command:
Get-WmiObject -Query "select * from win32_PnPEntity" | Where Name -like "MyDeviceName"
Or if you are unsure how the device is named as of now, this would return a complete list of "devices":
Get-WmiObject -Query "select * from win32_PnPEntity" | Select Name
Additionally, I couldn't find battery information in the registry - maybe someone more knowledge can expand on that because the registry probably contains the necessary information as it must be stored somewhere on the device.
Paulo Amaral's comment above is indeed the answer.
The code below will provide you with a command you can reuse to query the battery state of your device:
Get-PnpDevice -FriendlyName "*<Device Name>*" | ForEach-Object {
$local:test = $_ |
Get-PnpDeviceProperty -KeyName '{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2' |
Where Type -ne Empty;
if ($test) {
"To query battery for $($_.FriendlyName), run the following:"
" Get-PnpDeviceProperty -InstanceId $($test.InstanceId) -KeyName '{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2' | % Data"
""
"The result will look like this:";
Get-PnpDeviceProperty -InstanceId $($test.InstanceId) -KeyName '{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2' | % Data
}
}
For my <Headset> device, the output looked similar to:
To query battery for <Headset>, run the following:
Get-PnpDeviceProperty -InstanceId BTHENUM\{0000####-0000-####-####-############}_VID&########_PID&####\#&########&#&############_######### -KeyName '{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2'
The result will look like this:
90

How to programmatically eject locked HDD eSATA drive with PowerShell?

I am trying to eject eSATA HDD drive via "USB tray icon of windows" for safe remove, but it is not possible because "another program using the drive" error (I already tired of this stup## Windows error).
I tried this code on PowerShell:
$vol = get-wmiobject -Class Win32_Volume | where{$_.Name -eq 'F:\'}
$vol.DriveLetter = $null
$vol.Put()
$vol.Dismount($false, $false)
And this other:
$Eject = New-Object -comObject Shell.Application
$Eject.NameSpace(17).ParseName($usbDrvLetter+“:”).InvokeVerb(“Eject”)
And nothing happens.
Any method valid to get this to work?
Not sure but the overload definitions for the .Dismount() method are:
OverloadDefinitions
-------------------
System.Management.ManagementBaseObject Dismount(System.Boolean Force, System.Boolean Permanent)
So maybe change to: $Vol.Dismount($true, $true) effectively force the dismount.
I've tried testing this, except in general I think you should use the CIM cmdlets instead of -WMI. Get-WMIObject is deprecated in Windows PowerShell and has been removed from PowerShell Core.
It's also important to consider the potential return codes (documented here) from the Dismount method.
RETURN VALUE Return code Description
------------ ------------------------
0 Success
1 Access Denied
2 Volume Has Mount Points
3 Volume Does Not Support The No-Autoremount State
4 Force Option Required
To get the volume instance:
$Vol = Get-CimInstance -ClassName Win32_Volume -Filter "DriveLetter = 'E:'"
That's obviously similar enough to the older approach. However, invoking methods is done a little differently:
$Vol | Invoke-CimMethod -MethodName Dismount -Arguments #{ Force = $true; Permanent = $true }
ReturnValue PSComputerName
----------- --------------
2
And, it doesn't appear to dismount the drive. However, if I change the arguments:
$Vol | Invoke-CimMethod -MethodName Dismount -Arguments #{ Force = $true; Permanent = $false }
ReturnValue PSComputerName
----------- --------------
0
This does appear to dismount the drive, as Explorer shifted focus. However, the drive is still visible and when clicked can be accessed. I never saw the Safely eject message. It seems that Dismounting the drive is not equivalent to safely ejecting it.

Is there any method for getting details of all installed apps in a Windows device using shell commands

I need to get all installed applications and its details in a Windows device using shell commands. I tried using
Get-appxpackage
Get-WmiObject
wmic
Apps that were installed manually seems to be missing in the list. Please help by providing a better method.
An alternative can be to query the registry like this for example:
# HKLM - Local Machine
$InstalledSoftware = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
foreach($obj in $InstalledSoftware){write-host $obj.GetValue('DisplayName') -NoNewline; write-host " - " -NoNewline; write-host $obj.GetValue('DisplayVersion')}
# HKCU - Current User
InstalledSoftware = Get-ChildItem "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
foreach($obj in $InstalledSoftware){write-host $obj.GetValue('DisplayName') -NoNewline; write-host " - " -NoNewline; write-host $obj.GetValue('DisplayVersion')}
Check this page out for more:
https://www.codetwo.com/admins-blog/how-to-check-installed-software-version/
Tip! Browse these locations in the registry manually before you dig in as it will help you see the structure and understand what properties are available. If the information you're seeking is not there, you might just ditch this suggestion.
For Windows 64-bit and 32-bit apps use
Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Format-Table > C:\ws\apps.txt
the C:\ws\apps.txt need to be adjusted by you, to your output path.
I found the idea here, Social MS

Powershell 3.0 : Alternative to "Get-Volume"

I'm trying to get various properties for each hdd-volume on the computer.
I was using the cmdlet get-volume and then walking through it via foreach, but that cmdlet does not exist in Windows Server 2008. :(
Does anybody know an alternative?
I just need the drive letter, objectId/guid, free space, total space, and the name of each volume.
The WMI class Win32_Volume has the information you are looking for
Get-WMIObject -Class Win32_Volume | Select DriveLetter,FreeSpace,Capacity,DeviceID,Label
Which a little fancy footwork you can make the drive space properties looking a little more appealing.
Get-WmiObject -Class Win32_Volume |
Select DriveLetter,
#{Label="FreeSpace (In GB)";Expression={$_.Freespace/1gb}},
#{Label="Capacity (In GB)";Expression={$_.Capacity/1gb}},
DeviceID,Label |
Format-Table -AutoSize
Get-Volume is only in Powershell 4.
You can do this tho:
Get-WmiObject Win32_LogicalDisk | Select-Object DeviceID, Size, FreeSpace, VolumeName

Windows API for the location of Hiberfil.sys

Does anybody know if there is a Windows API to return the location of the hiberfil.sys ?
Many thanks
Hiberfil.sys is created when you enable hibernation and have hibernated your computer at least once. Its location can be determined like any other file: by directing the OS to search for it. Its usual location is in the root of your system drive, which is usually C:. This working powershell script was found here. See the link for the full script, but this is the core:
gwmi cim_datafile -filter "path='\\'" | ? {$_.name -match 'hiberfil.sys'} or
gwmi -Query "Associators of {Win32_Directory.Name='C:\'} Where ResultClass=CIM_DataFile" | ? {$_.name -match 'hiberfil.sys'}
Also helpful, Karl. E. Peterson's API reference:
http://vb.mvps.org/samples/apixref.asp
He also has made available for download some sample code, zipped up. Hope this helps...

Resources