How to locate Executable paths with WMIC and Powershell - python-3.x

I am using both python and Powershell and I can't figure out the discrepancies between the 2. Obviously one is using WMIC and the other is using Get-ItemProperty -path.
How can I get the path's from the WMIC for all executables. Python example as Follow:
if use_cached_program_list is False:
# traverse the software list
Data = subprocess.check_output(['wmic', 'product', 'get', 'name'])
program_list = sorted(str(Data).split("\\r\\r\\n"))
# Filter out string that contain no alphanumeric characters
program_list = [x.strip() for x in program_list if re.search('[a-zA-Z0-9]', x) is not None]
# Get absolute path of current file
sp = pathlib.Path(__file__).parent.absolute()
cached_file_path = os.path.join(sp, "Caches", cache_file)
with open(cached_file_path, "w") as fs:
# arrange the string and output to file
for i in range(0, len(program_list)):
item = program_list[i]
fs.write(item + "\n")
Returns an output of 477 "Programs" I use quotes on programs cause it returns, all sdk's whether it is extensions or runtimes as displayed below:
Active Directory Authentication Library for SQL Server
Adobe Acrobat Reader DC
Adobe Refresh Manager
Advanced IP Scanner 2.5
Application Verifier x64 External Package
Application Verifier x64 External Package
Application Verifier x64 External Package
Application Verifier x64 External Package
When I use Powershell, and the Get-ItemProperty and search the registry here is the code:
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\*" | Where-Object {$q + $_."(default)" -ne $null} | Select-Object #{ expression={$_.PSChildName}; label='Program'} ,#{ expression={$q + $_."(default)" +$q}; label='CommandLine'} | Export-Csv -Path .\programs.csv -Encoding ascii -NoTypeInformation
I have not updated this code above to remove all Double Quotations, but none the less still has same results.
To remove all Double Quotation marks the code is:
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\*" | Where "(default)" -ne $null |
Select #{ E={$_.PSChildName}; N='Program'} ,#{ E={$_."(default)".Trim('"')}; N='CommandLine'} |
export-csv .\programs.csv -Encoding ascii -NoType
here is the output:
"7zFM.exe","C:\Program Files\7-Zip\7zFM.exe"
"AcroRd32.exe","C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
"Adobe Audition CC.exe","""C:\Program Files\Adobe\Adobe Audition CC 2019\Adobe Audition CC.exe"""
"Adobe Media Encoder.exe","""C:\Program Files\Adobe\Adobe Media Encoder CC 2019\Adobe Media Encoder.exe"""
"Adobe Premiere Pro.exe","""C:\Program Files\Adobe\Adobe Premiere Pro CC 2019\Adobe Premiere Pro.exe"""
"AfterFX.exe","C:\Program Files\Adobe\Adobe After Effects CC 2019\Support Files\AfterFX.exe"
This results in only 75 applications installed. Reason is that it checks the uninstall key, and from what I know it appears many companies who develop software simply do not adhere to Microsoft's policies on registry keys. or did not use an MSI installer.
Now before anyone starts saying the Registry keys needed to search are both
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*
HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
Whether I use one or both of those registry paths they return the exact same results with both 32bit and 64 bit.
The Goal:
I am trying to get WMIC to return the path for all of the executables, and I will filter out the unwanted stuff later.
Any ideas?
Thank you

This is the same thing as "wmic product get name" in powershell. This class tends to be slow since it verifies every msi.
get-ciminstance win32_product | % name
Or you can do (powershell 5.1):
get-package | % name

Related

Azure Pipeline Extract Task 7zip

Unable to extract zip to destination with default usage of Extract Task its fails with error:
##[error]Unable to locate executable file: 'C:\azagent\A5\_work\_tasks\ExtractFiles_5e1e3830-fbfb-11e5-aab1-090c92bc4988\1.200.0\7zip\7z.exe'. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.
Stating its fails to locate default 7zip path. Tried to use custom PATH setting but also fails with the same error.
UPDATE
Issue seem to be caused by permissions of agent. Still haven't been able to execute Release with Admin privileges in service mode. When run in interactive mode as Admin the release executes successfully.
Task fails whenever admin permission is required.
From the error message, 7zip seems not installed on your self-hosted agent. Try to install the 7zip before you use the Extract Task.
Take Bash Task as an example:
brew install p7zip
For Windows, use the below PowerShell script to install:
$dlurl = 'https://7-zip.org/' + (Invoke-WebRequest -UseBasicParsing -Uri 'https://7-zip.org/' | Select-Object -ExpandProperty Links | Where-Object {($_.outerHTML -match 'Download')-and ($_.href -like "a/*") -and ($_.href -like "*-x64.exe")} | Select-Object -First 1 | Select-Object -ExpandProperty href)
# modified to work without IE
# above code from: https://perplexity.nl/windows-powershell/installing-or-updating-7-zip-using-powershell/
$installerPath = Join-Path $env:TEMP (Split-Path $dlurl -Leaf)
Invoke-WebRequest $dlurl -OutFile $installerPath
Start-Process -FilePath $installerPath -Args "/S" -Verb RunAs -Wait
Remove-Item $installerPath

How to use New-AzDataLakeGen2Item to send multiple files under a directory

Based on document from Microsoft
-Source
- Specify the local source file path which will be upload to a Datalake Gen2 file.
TABLE 13
Type: String
Position: Named
Default value: None
Accept pipeline input: True
Accept wildcard characters: False <-- no wildcard?
The doc also provided an example
PS C:\> $task = New-AzDataLakeGen2Item -FileSystem "testfilesystem" -Path "dir1/dir2/file1" -Source "c:\sourcefile.txt" -Force -asjob
Then what if I'd like to send all files under a directory, so that
-Source "c:\temp\*" <-- wildcard not allowed
-Source "c:\temp\" <-- "Could not find file..."
instead of
-Source "c:\sourcefile.txt"
I don't think you will be able to upload multiple files using New-AzDataLakeGen2Item Cmdlet.
You can however make use of azcopy tool to upload multiple files. Based on the documentation, it supports copy files from local to ADLS Gen2 account (and vice-versa) among other things.
Please see this link for more details: https://learn.microsoft.com/en-us/azure/storage/common/storage-ref-azcopy-copy.

WinSCP - How to download only folders/files 1 day old while excluding empty folders/files? [duplicate]

I am limited to PuTTY and WinSCP only.
I am trying to download log directories with log files. For example, I want to grab all log_files 6 days old or newer. log_dir2 and log_dir3 including the folders match the criteria, while log_dir1 and its files does not.
DIR/log_dir1/log_files % older than 6 days
DIR/log_dir2/log_files % meets criteria
DIR/log_dir3/log_files % meets criteria
My problem is that while the log_files of log_dir1 are not downloaded, the syntax I am currently using downloads the log_dir1 folder. Normally, not a big deal, but we are talking hundreds of log_dir folders (all empty as the files are older than 6 days). For reasons beyond my control, I cannot move or archive these old log directories with their log files.
My question is simply, how do I change my syntax to ignore folders that are older than 6 days as well as files.
get -filemask="*>6D" /DIR/* C:\temp
I have tried several different combinations of parameters and I have read the support page about Directory Masks and Path Masks. I cannot get any of them working (version issue?). Can anyone explain their syntax better than the help page. I will update tomorrow with the current version of WinSCP that I am using.
Time constraint in WinSCP file mask cannot be used for directories.
But you can prevent WinSCP from creating the empty folders. Use -rawtransfersettings switch with ExcludeEmptyDirectories setting.
get -rawtransfersettings ExcludeEmptyDirectories=1 -filemask="*>6D" /DIR/* C:\temp
This is the original answer, before WinSCP supported ExcludeEmptyDirectories. It might still be useful as a basis for implementations that have even more specific constraints.
You can implement this custom logic easily in PowerShell script with a use of WinSCP .NET assembly:
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "example.com"
UserName = "username"
Password = "password"
SshHostKeyFingerprint = "..."
}
$remotePath = "/remote/path"
$localPath = "C:\local\path"
$limit = (Get-Date).AddDays(-6)
$session = New-Object WinSCP.Session
# Connect
$session.Open($sessionOptions)
# Enumerate files to download
$fileInfos =
$session.EnumerateRemoteFiles(
$remotePath, $Null, [WinSCP.EnumerationOptions]::AllDirectories) |
Where-Object { $_.LastWriteTime -gt $limit }
foreach ($fileInfo in $fileInfos)
{
$localFilePath =
[WinSCP.RemotePath]::TranslateRemotePathToLocal(
$fileInfo.FullName, $remotePath, $localPath)
# If the corresponding local folder does not exist yet, create it
$localFileDir = Split-Path -Parent $localFilePath
if (!(Test-Path -Path $localFileDir))
{
Write-Host "Creating local directory $localFileDir..."
New-Item $localFileDir -ItemType directory | Out-Null
}
Write-Host "Downloading file $($fileInfo.FullName)..."
# Download file
$sourcePath = [WinSCP.RemotePath]::EscapeFileMask($fileInfo.FullName)
$transferResult = $session.GetFiles($sourcePath, $localFilePath)
# Did the download succeeded?
if (!$transferResult.IsSuccess)
{
# Print error (but continue with other files)
Write-Host ("Error downloading file ${remoteFilePath}: " +
$transferResult.Failures[0].Message)
}
}
$session.Dispose()
Write-Host "Done."
Run the script (download.ps1) like:
powershell.exe -ExecutionPolicy Unrestricted -File download.ps1

Blazor Wasm PWA IIS Deployment integrity error

I created a new Blazor PWA WebAssembly (last version default template) project and deployed it in a IIS in Windows Server to try PWA.
Installed the last .NET Core Hosting Bundle.
After publising it, I ran the script in the Microsoft Docs to rename dll files:
dir .\_framework\_bin | rename-item -NewName { $_.name -replace ".dll\b",".bin" } ((Get-Content .\_framework\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content .\_framework\blazor.boot.json
And the serviceworker renaming code too:
((Get-Content .\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content .\service-worker-assets.js
Then I deleted the compressed files as the docs says:
wwwroot\service-worker-assets.js.br
wwwroot\service-worker-assets.js.gz
wwwroot\_framework\blazor.boot.json.br
wwwroot\_framework\blazor.boot.json.gz
But I am still getting an error when I load the app:
What Am I missing here?
I guess that it has to do with the hashes and the renaming thing but cant find any solution in the BlazorĀ“s Github issues.
As a result of your modifications to the blazor.boot.json file, the integrity checks fails. service-worker-assets.js contains a list of files and their integrity hashes which are calculated at the time of publish.
You can manually recalculate the hashes using Bash/PowerShell, since you're using IIS, I'll provide the PowerShell script I used for a similar issue:
# make sure you're in the wwwroot folder of the published application
$JsFileContent = Get-Content -Path service-worker-assets.js -Raw
# remove JavaScript from contents so it can be interpreted as JSON
$Json = $JsFileContent.Replace("self.assetsManifest = ", "").Replace(";", "") | ConvertFrom-Json
# grab the assets JSON array
$Assets = $Json.assets
foreach ($Asset in $Assets) {
$OldHash = $Asset.hash
$Path = $Asset.url
$Signature = Get-FileHash -Path $Path -Algorithm SHA256
$SignatureBytes = [byte[]] -split ($Signature.Hash -replace '..', '0x$& ')
$SignatureBase64 = [System.Convert]::ToBase64String($SignatureBytes)
$NewHash = "sha256-$SignatureBase64"
If ($OldHash -ne $NewHash) {
Write-Host "Updating hash for $Path from $OldHash to $NewHash"
# slashes are escaped in the js-file, but PowerShell unescapes them automatically,
# we need to re-escape them
$OldHash = $OldHash.Replace("/", "\/")
$NewHash = $NewHash.Replace("/", "\/")
$JsFileContent = $JsFileContent.Replace("""$OldHash""", """$NewHash""")
}
}
Set-Content -Path service-worker-assets.js -Value $JsFileContent -NoNewline
This script iterates over all files listed inside of service-worker-assets.js, calculates the new hash for each file and updates the hash in the JavaScript file if it's different.
You have to execute the script with the published wwwroot folder as the current working directory.
I described this in more detail on my blog: Fix Blazor WebAssembly PWA integrity checks

Disable/enable completely input devices (mouse+keyboard+touchpad) in Windows10

I'm trying to disable/enable input devices in my laptop (win10), automatically (.reg file, python code etc)
I tried to use DevCon but after a lot of attempts it didn't work out for my touchpad and keyboard (I tried to disable, remove).
I searched the web and the solutions don't completely disable the devices (for example: Ctrl+Alt+Delete is not blocked).
I work on a windows 10 Laptop, You can assume that you have admin Privileges.
Have to check for Keyboard but for Mouse and Touchpad, you can use some Powershell commands to check and find out the actual device Classes and InstanceIDs and then turn off with an Admin elevated Powershell prompt.
The InstanceIDs of Mouse and Touchpad is different on different brands and types of Laptops, but first you can identify those with their Classes such as HIDClass. To get that fire up Powershell prompt(you've already tried REG and Python, so assuming you'll be okay with Powershell too (.ps1)) and run this command:
Get-PnpDevice | Where-Object {$_.Class -eq 'HIDClass'}
This may show 2 or 3 entries of which 1 belongs to Mouse and other to Touchpad, this would be a bit of trial and error, you have to pick any InstanceID to make filter more target specific and fire-up admin-elevated Powershell (search Powershell and click on "Run As Administrator") and run Disable-PnpDevice method like below(if InstanceId contains "ACPI"):
Get-PnpDevice | Where-Object {$_.Class -eq 'HIDClass' -and $_.InstanceId -like 'ACPI*'} | Disable-PnpDevice -Confirm:$false
This will disable Touchpad(in mine(Lenovo) it did disabled it) and then you can try out another InstanceID and disable the Mouse too in the same way. Voila !! both are turned off now.
If you prefer this in .ps1 script format then you need a self-elevating script which can enable/disable the devices without any halts, save this code in .ps1 file and then right-click > Run with PowerShell:
$Loc = Get-Location
"Security.Principal.Windows" | % { IEX "( [ $_`Principal ] [$_`Identity ]::GetCurrent() ).IsInRole( 'Administrator' )" } | ? {
$True | % { $Arguments = #('-NoProfile','-ExecutionPolicy Bypass','-NoExit','-File',"`"$($MyInvocation.MyCommand.Path)`"","\`"$Loc\`"");
Start-Process -FilePath PowerShell.exe -Verb RunAs -ArgumentList $Arguments; } }
Get-PnpDevice | Where-Object {$_.Class -eq 'HIDClass' -and $_.InstanceId -like 'ACPI*'} | Disable-PnpDevice -Confirm:$false
Read-Host
Note: If you in case disable the wrong or undesired device than for enabling it, in the same admin-elevated Powershell window run the same filter command (the Get-PnpDevice with filters) and replace Disable-PnpDevice with Enable-PnpDevice.
Let me know in comments if you still face issue with above commands.
Untested, but calling BlockInput() should do what you want. It blocks both keyboad and mouse input. It is however defined in user32.dll so you will need to use ctypes to access it:
import ctypes
ctypes.windll.user32.BlockInput(True)

Resources