Finding the path & product version of a file in powershell - powershell

I am try to create Powershell script to search for a sacrifice file (.exe) on the same machine or another machine in the network and return all the paths of the files with the product version for each one
I used the below code but I only was able to get the path only
$filename = 'example.exe'
(gdr -PSProvider 'FileSystem' | %{ ls -r $_.root} 2>$null | where { $_.name -eq ".EXE" })

(gdr -PSProvider 'FileSystem' | %{ ls -r $_.root} 2>$null | where { $_.name -eq "$filename" } | Select FullName,#{n='Version';e={$_.versioninfo.productversion}})

Related

How can I use a PowerShell output in the next command?

I am working on a PowerShell command to search across drives for a specific file. I am new to PowerShell so most of what I have already is just stuff I found online. At the moment I have this:
$ExclDrives = ('C')
>> Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Name -notin $ExclDrives} `
>> | % {write-host -f Green "Searching " $_.Root;get-childitem $_.Root -include *MyFile.txt -r `
>> | sort-object Length -descending}
Which outputs this:
Searching D:\
Searching E:\
Searching F:\
Directory: F:\MyDirectory
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 8/13/2022 12:03 AM 0 MyFile.txt
PS C:\Windows\system32>
I would like to know how I can take the directory that is listed in the output and use it in a following command such as:
cd F:\MyDirectory
If this is possible through piping or something I would really appreciate an answer :)
Thanks for reading
I wasn't really sure what the best way to handle this would be if multiple files were found. We wouldn't be able to change directory into the parent folders while the script was running nor would we be able to do so for all of the returned files unless we opened new PowerShell windows for each. Since it appears that you will be searching for specific files which I assume will not return too many results and not knowing your ultimate goal I went with opening a new file explorer window for each file with the file being highlighted/selected.
$excludeDrives = ('C')
Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Name -notin $excludeDrives } |
ForEach-Object {
Write-Host -f Green 'Searching ' $_.Root
Get-ChildItem -Path $_.Root -Recurse -Include *MyFile.txt -ErrorAction SilentlyContinue |
ForEach-Object {
# This line will open a file explorer window with the file highlighted
explorer.exe /select, $_
# This line will send the file object out through the pipeline
$_
} | Sort-Object Length -Descending
}
To answer your question about how to access the file's directory in the next command, you can use Foreach-Object and $_.Directory:
Get-ChildItem -Path $_.Root -Recurse -Include *MyFile.txt -ErrorAction SilentlyContinue |
Sort-Object Length -Descending |
ForEach-Object {
# Using the pipeline we can pass object along and access them
# using a special automatic variable called $_
# a property exists on FileInfo objects called Directory
'The directory is ' + $_.Directory
}
UPDATE
Hopefully this will answer the question in your comment
$ExclDrives = ('C')
Get-PSDrive -PSProvider FileSystem |
Where-Object { $_.Name -in $ExclDrives } |
ForEach-Object {
Write-Host -f Green 'Searching ' $_.Root
Get-ChildItem $_.Root -Include *MyFile.txt -Recurse -ErrorAction SilentlyContinue |
ForEach-Object {
# do whatever you want with the file. Reference using $_
Write-Host "Found Filename: $($_.Name)`tDirectory: $($_.Directory)" -ForegroundColor Cyan
explorer.exe /select, $_
# output the fileinfo object, in this case
# to the next command in the pipeline which is Sort-Object
$_
} |
Sort-Object Length -Descending
}

Powershell Script to find and delete a subkey in the Registry for all users

I am attempting to find and delete a specific Subkey and it's contents for each user of the computer.
I found this post: https://www.pdq.com/blog/modifying-the-registry-users-powershell/ which does most of what I need it to do. However, I need to not only search the registry, but to also delete a subkey and it's contents.
Here is the script that I've copied from the above mentioned site:
$PatternSID = 'S-1-5-21-\d+-\d+\-\d+\-\d+$'
$ProfileList = gp 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*' | Where-Object {$_.PSChildName -match $PatternSID} |
Select #{name="SID";expression={$_.PSChildName}},
#{name="UserHive";expression={"$($_.ProfileImagePath)\ntuser.dat"}},
#{name="Username";expression={$_.ProfileImagePath -replace '^(.*[\\\/])', ''}}
$LoadedHives = gci Registry::HKEY_USERS | ? {$_.PSChildname -match $PatternSID} | Select #{name="SID";expression={$_.PSChildName}}
$UnloadedHives = Compare-Object $ProfileList.SID $LoadedHives.SID | Select #{name="SID";expression={$_.InputObject}}, UserHive, Username
Foreach ($item in $ProfileList) {
IF ($item.SID -in $UnloadedHives.SID) {
reg load HKU\$($Item.SID) $($Item.UserHive) | Out-Null
}
"{0}" -f $($item.Username) | Write-Output
Get-ItemProperty registry::HKEY_USERS\$($Item.SID)\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
Foreach {"{0} {1}" -f " Program:", $($_.DisplayName) | Write-Output}
Get-ItemProperty registry::HKEY_USERS\$($Item.SID)\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* |
Foreach {"{0} {1}" -f " Program:", $($_.DisplayName) | Write-Output}
}
This returns a list of all programs installed per user. However, when I try to delete the subkey using this command, I get an error that the path could not be found. What am I doing wrong?
Remove-Item -Path HKEY_USERS\$($Item.SID)\Software\Microsoft\Windows\CurrentVersion\Uninstall\Test

Check shared drive is already mapped

I'm using PowerShell for the first time to check if a unc path is already mapped, and if it is delete it to create it again under specific credentials.
The problem I have found is if the path exists in the net use list but has a drive letter, you have to delete it by the drive letter which can be of course random. So I need to find out the drive letter when I match it but I am clueless as to how.
$userPass = '/user:Domain\User password';
$ltr = ls function:[d-z]: -n | ?{ !(test-path $_) } | random;
$share = '\\\\server\\folder';
$newMap = 'net use '+ $ltr + ' '$share + ' '$userPass;
foreach ($con in net use) {
if ($con -match $share) {
$MappedLetter = /*something here to find the matched drive?*/
if ($MappedLetter) {
net use $MappedLetter /delete
} else {
net use $share /delete
}
}
};
net use $newMap;
[Edit]
I have tried the Get-PSDrive but this only works IF the UNC path is mapped to a drive. As these can at times be a "zombie", i.e. exist in net use but have no letter, this method won't always work. I can combine the two methods (above an Get-PSDrive) but if anyone has a cleaner way please let me know!
You should be able to check whether a particular share is already mapped via Get-PSDrive:
$share = '\\server\share'
$drive = Get-PSDrive |
Where-Object { $_.DisplayRoot -eq $share } |
Select-Object -Expand Name
if ($drive) {
"${share} is already mapped to ${drive}."
}
If you just want to remove the drive in case it is mapped you could do something like this:
Get-PSDrive | Where-Object {
$_.DisplayRoot -eq $share
} | Remove-PSDrive
Update:
AFAIK PowerShell can't enumerate and remove disconnected drives directly. You can obtain that information from the registry:
$share = '\\server\share'
$drive = Get-ItemProperty 'HKCU:Network\*' |
Where-Object { $_.RemotePath -eq $share } |
Select-Object -Expand PSChildName
or parse it out of the net use output:
net use | Where-Object {
$_ -match '(?<=^Unavailable\s+)\w:'
} | ForEach-Object {
$matches[0]
}
However, from what I know you still won't be able to remove the drive (e.g. via net use) as long as it remains disconnected. For removing a disconnected drive (e.g. when a share has become permanently unavailable) that you'd need to remove the mapping information from the registry:
$share = '\\server\share'
Get-ItemProperty 'HKCU:Network\*' |
Where-Object { $_.RemotePath -eq $share } |
Remove-Item
# also remove mount point in Windows Explorer
$key = 'Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2'
$subkey = Join-Path $key ($share -replace '\\', '#')
Get-ItemProperty "HKCU:${subkey}" | Remove-Item

Find a particular file name existence and execute batch command

I am looking for a PS script which will search for a particular file name and check its existence. If file exists it should execute a batch command.
$version = "1.1.0"
$packageName = "example.DTO.$version"
Get-ChildItem "d:\Test" | Where-Object { $_.Name -match "$packageName.nupkg" }
and my batch command
C:\NugetRestore\nuget.exe push "d:\Test\$packageName.nupkg" saranuget -Source "http://123.456.78.90/myget" -Timeout 120
I am unable to integrate both this.
This covers where the test matches multiple files:
$version = "1.1.0"
$packageName = "example.DTO.$version"
$FileCheck = Get-ChildItem "d:\Test" | Where-Object { $_.Name -match "$packageName.nupkg" }
$FileCheck | ForEach-Object {
C:\NugetRestore\nuget.exe push "$($_.Fullname)" saranuget -Source "http://123.456.78.90/myget" -Timeout 120
}

powershell how to loop over files and zip them

First time powershell development - have to say not intuitive for a linux scripter.
need to loop over files to zip them and getting errors - anyone have some feedback on a good one liner?
gci C:\temp -r *.csv |
Where-Object { $_.lastwritetime -lt (Get-date).AddDays(-10)} |
ForEach-Object {'c:\temp\bin\gzip.exe' $_.FullName}
You're missing the call (&) operator to actually execute the command in the string. If you don't do this, the string is printed out as the result of an expression evaluation (instead of as a command.)
gci C:\temp -r *.csv `
| Where-Object { ... } `
| ForEach-Object { & 'c:\temp\bin\gzip.exe' $_.FullName}
Incidentally, if you install the PowerShell Community Extensions (http://pscx.codeplex.com) then this becomes much simpler:
ls c:\temp -r *.csv `
| where { ... }
| write-gzip
Applications can be executed in Powershell just by giving their name / path, you don't have to enclose them in quotes as strings and then use iex or &:
c:\temp\bin\gzip.exe $_.FullName
would work for the zipping part.
The following version of your script could come in handy when you can't rely on external tools:
gci C:\temp -recurse *.csv |
Where-Object { $_.lastwritetime -lt (Get-date).AddDays(-10)} |
ForEach-Object {
$zip = $_.fullname -replace "\.csv",".zip";
new-item -type File $zip -force;
((new-object -com shell.application).namespace($zip)).copyhere($_.fullname)
}