How to sign all the msi file which are under folder? - powershell

I am using signtool to sign my msi.
How to recursively search all the msi in a folder and subfolder then sign them all?

The previous 2 answers show a PowerShell solution.
You can accomplish this easily enough from a CMD.EXE Command Prompt as well.
for /r "yourRootFolder" %F in (*.msi) do signtool sign /a "%F"
Obviously you need to modify your signtool options to suit your needs. The important bit is %F will iteretively hold the name of each .MSI file.
If you want to run the command from within a batch file, then the % must be doubled, so %F becomes %%F in both places.

Here's an example using a code signing certificate (I have only one certificate in $cert):
$cert = Get-ChildItem -Path Cert: -CodeSigningCert -Recurse
Get-ChildItem -Path C:\MsiFolder -Filter *.msi -Recurse | Set-AuthenticodeSignature -Certificate $cert

Assuming you know what command line parameters you need for the MSI signing tool are you can get all MSIs under a given folder like this:
Get-ChildItem -recurse -path C:\MsiFolder -Include *.msi | ForEach-Object {
$msiPath = $_.FullName
$output = & the_msi_sign_tool.exe -msifile $msiPath -parameterB -parameterC 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Error $output
}
}

Only one password prompt!
$signExe = 'C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe'
$files = gci 'C:\Temp\*' -Include *.msi | %{('"{0}"' -f $_.FullName)}
$fingerprint = '00000000000000000000000000000000000000000'
$timestampUrl = 'http://rfc3161timestamp.globalsign.com/advanced'
$filesInputArg = $files -join " "
.$signExe sign /tr $timestampUrl /td SHA256 /sha1 $fingerprint $filesInputArg

Related

GPG - Can't Find File Specified Error Even Though File is There

I have a PowerShell script where I'm assigning two files to a variable, using that variable in the Get-ChildItem cmdlet with the -Include parameters. I assign the result of Get-ChildItem to a variable and then write the contents of the variable to the logs. The files are clearly in the list, but when I use GPG to encrypt, it's saying the file cannot be found.
File filter variable:
$FileFilter = 'status_*.csv','financial_transactions_*.csv'
Writing getting the files and writing the result out:
$allfiles = Get-ChildItem -Path $Source -Include $FileFilter -Recurse
Write-Host $allfiles
Result in the logs:
E:\temp\reports\2022\07\01\financial_transactions_20220701_000.CSV
E:\temp\reports\2022\07\01\status_20220701_000.CSV
E:\temp\reports\2022\07\02\status_20220702_000.CSV
Full code to encrypt the file:
Get-ChildItem -Path $Source -Include $FileFilter -Recurse | ForEach-Object -Verbose {
$FileFullPath = $_.FullName
Write-Host "Encrypting" $FileFullPath
$NewEncryptFile = $_.FullName + '.PGP'
Write-Host "New file name is "$NewEncryptFile"."
Write-Host "In test. Using GnuPG."
Write-Host $NewEncryptFile
Write-Host $FileFullPath
Start-Process -filepath $GPGExePath -RedirectStandardError "E:\Scripts\error.txt" -Wait -ArgumentList "--batch --yes --output $NewEncryptFile --encrypt --recipient $GPGUser $FileFullPath"
}
I write out the path to the CSV file and the path where the encrypted file needs to go, which is the same location. I have physically gone to the location of the CSV files and it is there., I get the error "Error: This command cannot be run due to the error: The system cannot find the file specified."
When I assign one file to the $FileFilter variable, the GPG code works.

Use Invoke-Item calling .exe with variable folder path and passing /qn argument

I struggling to find whats wrong with my code.
Im trying to uninstall an app on several Windows 10 clients, where the path to the .exe is different on any machine. I use Get-ChildItem to get that specific folder. Now im trying to execute that path with the .exe at the end and add a /qn trigger to silently deinstall.
However, i always get back errors regarding the Invoke-Item function.
Here is my script:
First im trying to find the variable foldername inside the app folder:
$path_to_exe = Get-ChildItem -Path "C:\Program Files\ApplicationName" -Include "installer.exe" -Recurse |
Where-Object { $_.FullName -match '\{(.*)\}' }
Which gives me the path as a Get-ChildItem response.
Now i convert the path given from Get-ChildItem to a "Normal" Path
$path_to_exe = Convert-Path $Path_to_exe.PSPath
Now i try to call the path i found with the /qn trigger to silently deinstall.
"`"$path_to_exe`"" + " /qn" | Invoke-Item
Im 100% sure that my approach is a beginner tier one.
If anyone has a better idea, please educate me.
Thanks :)
EDIT:
The manufacturer states i should use the following:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{1D9F5D88-12AA-427F-8A33-DED71D60E4D9} - MsiExec.exe /X{1D9F5D88-12AA-427F-8A33-DED71D60E4D9}
Does anybody have an idea how i can extract that guid from the Get-ChildItem registry query?
get-package "*applicationname*" | uninstall-package
I finally figured it out! As i knew, i had the wrong approach. I was making it way to complicated trying to parse the EXE file to a seperate powershell instance and adding arguments.
I rewrote my whole code using the msiexec function.
So first i needed to find out the GUID of the app using the Get-ChildItem function.
$Path_to_GUID = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall |
Get-ItemProperty |
Where-Object {$_.DisplayName -match "Application Name" } |
Select-Object -Property DisplayName, UninstallString
Now i had the desired path of that Get-ChildItem object, with the .UninstallString property.
Since i only want the GUID itself, i used the Split-Path function to separate the path by the folder name/GUID which in the beginning somewhat looked like this:
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{xxxxxx-xxxx-xxxx-xxxx}\installer.exe
So using the Split-Path function i first only cut the -Parent part.
$Path_to_GUID = Split-Path -Path $Path_to_GUID.UninstallString -Parent
Which gave me the path like this, without the installer.exe at the end:
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{xxxxxx-xxxx-xxxx-xxxx}
So now i only want the part of the path with the curly braces using the -Leaf argument:
$Path_to_GUID = Split-Path $Path_to_GUID -Leaf
Which gave me the desired string:
{xxxxxx-xxxx-xxxx-xxxx}
Now i just had to uninstall using msiexec and adding the silent parameter:
msiexec /x $Path_to_GUID /qn
Here's the full code (Powershell):
$Path_to_GUID = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall |
Get-ItemProperty |
Where-Object {$_.DisplayName -match "Application Name" } |
Select-Object -Property DisplayName, UninstallString
$Path_to_GUID = Split-Path -Path $Path_to_GUID.UninstallString -Parent
$Path_to_GUID = Split-Path $Path_to_GUID -Leaf
msiexec /x $Path_to_GUID /qn

Windows PowerShell is in NonInteractive mode. Read and Prompt functionality is not available

I am new to the power shell scripting. I am trying to delete all files except one folder and one file. I run this script by using jenkins it showing error called " Windows PowerShell is in NonInteractive mode. Read and Prompt functionality is not available." And i am trying to run this script in powershell window but it asking Confirmation [Y/N]. I need to run this script by using jenkins please help me.
$Path = "C:\TeamCity\buildAgent2\work"
$exclude = #("*.old", "*directory.map")
Get-ChildItem $Path -Exclude $exclude | Remove-Item -Force -Confirm:$false -ErrorAction Stop| echo Y
You need to add the Recurse parameter to the remove command.
Like that:
Remove-Item -Recurse -Force
guiwhatsthat is correct your code should like this;
$Path = "C:\TeamCity\buildAgent2\work"
$exclude = #("*.old", "*directory.map")
Get-ChildItem $Path -Exclude $exclude | Remove-Item -Recurse -Force -Confirm:$false -ErrorAction Stop

How can I loop through specific file names with the Compress-Archive command in Windows PowerShell?

I am not too familiar with Windows PowerShell (and Windows console commands in general), but I wish to write a batch file which can create sperated .zip archives from specific files in a folder, then delete all but the .zip files. So, I have a folder as "C:\myfolder\" and some files in it like:
myfile0001.a
myfile0001.b
myfile0001.c
myfile0002.a
myfile0002.b
myfile0002.c
myfile0003.a
myfile0003.b
myfile0003.c
... and so on.
I want a create a .zip for every myfileXXXX.a + myfileXXXX.b + myfileXXXX.c package and name the .zips as the file names (for example myfile0001.zip would contain myfile0001.a + myfile0001.b + myfile0001.c).
I know that I can use this code to create each .zip archive one-by-one:
powershell -Command "& {Compress-Archive -Path C:\myfolder\myfile0001.* -CompressionLevel Optimal -DestinationPath C:\myfolder\myfile0001.zip}"
And this code working fine to delete all but the .zip archives
powershell -Command "& {Remove-Item C:\myfolder\*.* -Exclude *.zip}"
What I cannot solve is to create a for cycle which can loop through all myfileXXXX.* and create a myfileXXXX.zip using the XXXX as the increasing value.
In PowerShell, you could do:
Get-ChildItem -Path 'C:\myfolder' -File | Where-Object { $_.BaseName -match 'myfile\d{4}' } | Group-Object BaseName | ForEach-Object {
$target = Join-Path -Path ($_.Group[0].DirectoryName) -ChildPath ('{0}.zip' -f $_.Group[0].BaseName)
$_.Group | Compress-Archive -CompressionLevel Optimal -DestinationPath $target
$_.Group | Remove-Item -Force
}
Writing it as commandline gets a little ugly, but here you go:
powershell -Command "& {Get-ChildItem -Path 'C:\myfolder' -File | Where-Object { $_.BaseName -match 'myfile\d{4}' } | Group-Object BaseName | ForEach-Object { $target = Join-Path -Path ($_.Group[0].DirectoryName) -ChildPath ('{0}.zip' -f $_.Group[0].BaseName); $_.Group | Compress-Archive -CompressionLevel Optimal -DestinationPath $target; $_.Group | Remove-Item -Force}}"
I cannot still test this as I am not on a windows host now, but something like this. It needs to be saved as a .cmd or .bat file:
#echo off
for %%i in (C:\myfolder\*) do (
powershell -Command "& {Compress-Archive -Path C:\myfolder\%%~ni.* -CompressionLevel Optimal -DestinationPath C:\myfolder\%%~ni.zip}"
)
How's this? (Just use powershell) Zip files based on the basename. .zip automatically gets added to the archive filename.
powershell "ls | foreach { compress-archive $_ $_.basename -update -verbose }"
VERBOSE: The archive file path 'C:\users\js\foo\file1' supplied to the DestinationPath patameter does not include .zip extension. Hence .zip is
appended to the supplied DestinationPath path and the archive file would be created at 'C:\users\js\foo\file1.zip'.
VERBOSE: Preparing to compress...
VERBOSE: Performing the operation "Compress-Archive" on target "C:\users\js\foo\file1.1".
VERBOSE: Adding 'C:\users\js\foo\file1.1'.
VERBOSE: The archive file path 'C:\users\js\foo\file1' supplied to the DestinationPath patameter does not include .zip extension. Hence .zip is
appended to the supplied DestinationPath path and the archive file would be created at 'C:\users\js\foo\file1.zip'.
VERBOSE: Preparing to compress...
VERBOSE: Performing the operation "Compress-Archive" on target "C:\users\js\foo\file1.2".
VERBOSE: Adding 'C:\users\js\foo\file1.2'.
VERBOSE: The archive file path 'C:\users\js\foo\file1' supplied to the DestinationPath patameter does not include .zip extension. Hence .zip is
appended to the supplied DestinationPath path and the archive file would be created at 'C:\users\js\foo\file1.zip'.
VERBOSE: Preparing to compress...
VERBOSE: Performing the operation "Compress-Archive" on target "C:\users\js\foo\file1.3".
VERBOSE: Adding 'C:\users\js\foo\file1.3'.

powershell script to archive files in many subfolders

i am trying to write down a script which can help me to archive multiple files in multiple subdirs. Also i need to exclude specific files.
So far i got that few lines script
$files = Get-ChildItem -Recurse -path "D:\path\to\folder" -Exclude *i.jpeg |
Where-Object { $_.FullName -notmatch '\\excludedir($|\\)' }
foreach ($file in $files)
{
C:\Program Files\7-zip\7z.exe" a -t7z -mx=9 -ms=on $file
}
Basically its searches recursively all subfolders for .jpeg files and gives me the list of them excluding the ones that ends with 'i'.jpeg lets say 'photoi.jpeg'.
This is working, but i cannot make it to the next step as i need to run 7zip for all listed files.
Can someone help me out here.
Thanks in advance :)
Not sure if you are trying save one big zip lots of individual ones, however I do something like this:
Set-Alias sz "C:\Program Files\7-zip\7z.exe"
$files = Get-ChildItem -Recurse -path "D:\path\to\folder" -Exclude *i.jpeg |
Where-Object { $_.FullName -notmatch '\\excludedir($|\\)' }
foreach ($file in $files)
{
$output = sz a -t7z -mx=9 -ms=on "$File" 2>&1
}
You might have to modify the zipping line has I have tested it using your command line options. Another nice touch is that I have captured the output of the command for reporting purposes.
You need to pass filenames, not objects, to 7z command.
#listfile syntax can help:
Get-ChildItem ...| Where-Object ...| select -expand fullname| out-file alist.txt -encoding utf8
'C:\Program Files\7-zip\7z.exe' a archive.7z -mx=9 -ms=on `#alist.txt
Remove-item .\alist.txt
note the backtick before #