Not able to exit from the powershell console after script execution - windows

I am trying to create a script for my class to automatically create a folder monthDay wise and open it in Visual Studio Code. However, after the script executes the powershell console remains open until I close it manually or I close VSCode. I just want the console to go away after it executes. Here is the script: Please tell me how to do it..
# Hash table for months
$hash_month = #{1="jan";2="feb";3="mar";4="apr";5="may";6="june";7="july";8="aug";9="sep";10="oct";11="nov";12="dec"}
#extracting date
$date = (Get-Date).Day
#extracing month
$month = (Get-Date).Month
# getting month name from the hash table
$month_name= $hash_month[$month]
# Creating the Directory with monthDate
# This command will create a dir if it does not exist, or it will simply not execute if the directory exists
[System.IO.Directory]::CreateDirectory("$month_name$date")
# changing dir
cd $month_name$date
# opening the dir in vscode
code .
# currently not able to exit from console after execution of script
exit 0
I have attached the screenshot of the window, I just want the console to go away but NOT vscode.
Powershell and VSCode Screenshot

I made 2 changes here:
The path creation is handled differently, which has nothing to do with the question, but your way was not creating the path for me.
Used Start-Process with hidden window to instantiate VSCode and make the $pid kill method work.
Full script:
# Hash table for months
$hash_month = #{1 = "jan"; 2 = "feb"; 3 = "mar"; 4 = "apr"; 5 = "may"; 6 = "june"; 7 = "july"; 8 = "aug"; 9 = "sep"; 10 = "oct"; 11 = "nov"; 12 = "dec" }
#extracting date
$date = (Get-Date).Day
#extracing month
$month = (Get-Date).Month
# getting month name from the hash table
$month_name = $hash_month[$month]
# Creating the Directory with monthDate
# This command will create a dir if it does not exist, or it will simply not execute if the directory exists
$path = $month_name + $date
if (!(Test-Path $path)) {
New-Item $path -ItemType Directory
}
# # changing dir
cd $path
# # opening the dir in vscode with Start-Process
Start-Process -FilePath "code" -ArgumentList "." -WindowStyle Hidden
# # currently not able to exit from console after execution of script
Stop-Process $pid

Related

Powershell IF conditional isn't firing in the way I expected. Unsure what I'm doing wrong

I am writing a simple script that makes use of 7zip's command-line to extract archives within folders and then delete the original archives.
There is a part of my script that isn't behaving how I would expect it to. I can't get my if statement to trigger correctly. Here's a snippet of the code:
if($CurrentRar.Contains(".part1.rar")){
[void] $RarGroup.Add($CurrentRar)
# Value of CurrentRar:
# Factory_Selection_2.part1.rar
$CurrentRarBase = $CurrentRar.TrimEnd(".part1.rar")
# Value: Factory_Selection_2
for ($j = 1; $j -lt $AllRarfiles.Count; $j++){
$NextRar = $AllRarfiles[$j].Name
# Value: Factory_Selection_2.part2.rar
if($NextRar.Contains("$CurrentRarBase.part$j.rar")){
Write-Host "Test Hit" -ForegroundColor Green
# Never fires, and I have no idea why
# [void] $RarGroup.Add($NextRar)
}
}
$RarGroups.Add($RarGroup)
}
if($NextRar.Contains("$CurrentRarBase.part$j.rar")) is the line that I can't get to fire.
If I shorten it to if($NextRar.Contains("$CurrentRarBase.part")), it fires true. But as soon as I add the inline $j it always triggers false. I've tried casting $j to string but it still doesn't work. Am I missing something stupid?
Appreciate any help.
The issue seems to be your for statement and the fact that an array / list is zero-indexed (means they start with 0).
In your case, the index 0 of $AllRarfiles is probably the part1 and your for statement starts with 1, but the file name of index 1 does not contain part1 ($NextRar.Contains("$CurrentRarBase.part$j.rar"), but part2 ($j + 1).
As table comparison
Index / $j
Value
Built string for comparison (with Index)
0
Factory_Selection_2.part1.rar
Factory_Selection_2.part0.rar
1
Factory_Selection_2.part2.rar
Factory_Selection_2.part1.rar
2
Factory_Selection_2.part3.rar
Factory_Selection_2.part2.rar
3
Factory_Selection_2.part4.rar
Factory_Selection_2.part3.rar
Another simpler approach
Since it seems you want to group split RAR files which belong together, you could also use a simpler approach with Group-Object
# collect and group all RAR files.
$rarGroups = Get-ChildItem -LiteralPath 'C:\somewhere\' -Filter '*.rar' | Group-Object -Property { $_.Name -replace '\.part\d+\.rar$' }
# do some stuff afterwards
foreach($rarGroup in $rarGroups){
Write-Verbose -Verbose "Processing RAR group: $($rarGroup.Name)"
foreach($rarFile in $rarGroup.Group) {
Write-Verbose -Verbose "`tCurrent RAR file: $($rarFile.Name)"
# do some stuff per file
}
}

How to convert a Windows CMD Forloop in PowerShell

I have the following code in command shell code.
SET MYdir=%NewPath%\%CUST%\SuppliesTypes
SET "MYsCount=1"
SET /p MYsCount="Number of MYs in project? (default: %MYSCount%): "
for /L %%a in (1,1,%MYsCount%) do (
SET /p MYNums="Enter %%a MY Number: "
call md "%MYdir%\MY_%%MYNums%%"
)
SET "MYsCount="
However, I am converting my code from CMD to PowerShell. I do not fully understand the correct way to convert over. Here might be how it should be done, but it's not working as it just jumps right through.
SET MYdir=%NewPath%\%CUST%\Product
SET "MYsCount=1"
SET /p MYsCount="Number of MYs in project? (default: %MYSCount%): "
For ($MYsCount = 1; $MYsCount -eq 10; $MYsCount++){
SET /p MyNums="Enter %%a Product Numbers: "
CALL MD "%MYdir%\%CUST%\Product_%%"
}
SET "$MYsCount="
I've looked at the following sites and articles:
PowerShell Basics: Programming With Loops (Helped validate)
How to do a forloop in a Django template? (Didn't really help)
Windows PowerShell Cookbook, 3rd Edition (Page 170)
I am running this code inside a While-Loop.
Thanks for your help!
You have an interesting amalgam of batch file and powershell there in your second code block. It is hard to read when some things are one language and some things are another. Let's see if we can't get it all into PowerShell here.
$MYdir = "$NewPath\$CUST\Product"
$MYsCount = 1
$UserMYsCount = Read-Host "Number of MYs in project? (default: $MYSCount): "
If([string]::IsNullOrEmpty($UserMYsCount){
$UserMYsCount = $MYsCount
}
For ($i = 1; $i -le $UserMYsCount; $I++){
$MyNums = Read-Host "Enter $i Product Numbers: "
New-Item -Path "$MYdir\MY_$MyNums" -ItemType Directory
}
I believe the issue is coming from how you are declaring your variables. SET creates the variables as environment variables that powershell does not access natively. Below is how I would write up your section of code:
$MYDir = "$env:NewPath\$env:CUST\SuppliesTypes"
$MYsCount = 1
$MYsCount = read-host -prompt "Number of MYs in project? (default: $MYSCount): "
foreach ($a in 0..$MYsCount){
$MYNums = Read-Host -Prompt "Enter $a Product Numbers: "
New-Item -Path "$MYDir\MY_$MYNums" -ItemType Directory
}
$MYsCount = $null
I used a foreach loop instead of a normal for loop because you were incrementing by one each time and I have noticed a small performance gain from using foreach when the step is not complicated. 0..$variable is a short hand for using each number from 0 to the declared variable.
If you did want to use a for loop as you mentioned then you could use:
For ($MYsCount = 1; $MYsCount -eq 10; $MYsCount++){
as you had expected. This loop will only stop if the $MYsCount variable equals 10 though so if someone set the variable to something above 10 it would run indefinitely.

Batch script or CMD for daily task on directory content by date

I admit I am a noob when it comes to CMD and bat scripting hence maybe my question has already been answered but I couldn't find it because I am unfamiliar with the terminology.
Basically I am currently running CMD to create a txt file for a directory content, that works fine but I would like to improve this process and started to look into a batch file to run this for multiple directories and by date but only get confused with the commands.
I would really appreciated if you maybe show me the right direction to look up the possible commands. Here is was I am basically trying to achieve:
Scan Directory 1, create log file with all content (filename) with modification of date DDMMYYYY and save under Directory 1 (existing on Desktop)
Repeat above for Directory 2, 3, 4 etc.
Now I am not sure how to approach this and where to start. It looks so simply yet I am have not managed to get to work.
assuming you are on Vista or better and your date format is dd/mm/yyyy:
for /d %%a in ("%userprofile%\Desktop\Directory*") do (
for %%b in ("%%~fa\*") do (
set "fname=%%~fb"
for /f %%c in ("%%~tb") do set "fdate=%%c"
setlocal enabledelayedexpansion
echo !fname! !fdate:/=! >> "%%~fa\LOGFILE.TXT"
endlocal
)
)
First of all your batch script to parse current date-time will be locale specific. As long as you do not plan to use it on non-US Windows it will be fine. My solution was to use simple VBS script to generate current timestamps
So code of my batch file looks like
#echo off
call GetToday.bat
call %TEMP%\SetToday.bat
SET LOGFILE=Log.%TODAY%.log
echo %LOGFILE%
Use your log here
GetToday.bat:
#echo off
set TOOLS_HOME=%~dp0
cscript /NoLogo %TOOLS_HOME%\Today.vbs >%TEMP%\SetToday.bat
call %TEMP%\SetToday.bat
Today.vbs:
Dim d
d = Now
WScript.Echo "SET TODAY=" & Get2Digit(Year(d)) & Get2Digit(Month(d)) & Get2Digit(Day(d))
Function Get2Digit(value)
if 10 > value Then
Get2Digit = "0" & value
Else
Get2Digit = Right(value, 2)
End If
End Function
However given Today.vbs generates today date in form YYMMDD. From my experience such suffixes are much more useful, you could just sort you files by name to find specific date
In PowerShell something like this should work:
$folders = 'C:\path\to\Directory1', 'C:\path\to\Directory2', ...
$refDate = (Get-Date '2013-05-27').Date
$recurse = $false
foreach ($d in $folders) {
$output = Join-Path $d 'filelist.txt'
Get-ChildItem $d -Recurse:$recurse | ? {
-not $_.PSIsContainer -and $_.LastWriteTime.Date -eq $refDate
} | % { $_.Name } | Out-File $output
}
If you want to recurse into the subfolders of the scanned folders you need to change $recurse to $true and perhaps change $_.Name to $_.FullName, so you get the filename with the full path instead of just the filename.

Call a script in SharePoint PowerShell post-deployment command line with array in parameters

I try to call on post-deployment action a powerShell script with an array parameter, but without success.
Here is the script:
param(
[string[]]$ModelNameList = "DefaultModelName"
)
Write-Host "Number of Models is: $($ModelNameList.Count)"
and this is the post-deployment command line:
%windir%\sysnative\windowspowershell\v1.0\powershell -File "$(ProjectDir)Scripts\Post_Deployment\Script.Post-Deployment.ps1" -ModelNameList "m2","m1"
Result : Number of Models is: 1
Running the same script in SharePoint2010 Management Shell return the correct result.
Result : Number of Models is: 2
CMD doesn't know anything about PowerShell arrays, so it passes "m2","m1" into the powershell script as a single string. You can see that when you add
Write-Host $ModelNameList[0]
Write-Host $ModelNameList[0].GetType()
to your PowerShell script. I think you have to split the argument inside your script:
if ($ModelNameList[0] -match ',') {
$ModelNameList = $ModelNameList[0].Split(',')
}

Programmatically Install Certificate into Mozilla

Is there a way to programmatically install a certificate into mozilla? We're trying to script everything to eliminate deviations in environment so installing it by hand through mozilla preferences does not work for our needs.
I assume theres a way to do it with certutil, but I am not sure of Mozilla's internals, etc.
Here is an alternative way that doesn't override the existing certificates:
[bash fragment for linux systems]
certificateFile="MyCa.cert.pem"
certificateName="MyCA Name"
for certDB in $(find ~/.mozilla* ~/.thunderbird -name "cert8.db")
do
certDir=$(dirname ${certDB});
#log "mozilla certificate" "install '${certificateName}' in ${certDir}"
certutil -A -n "${certificateName}" -t "TCu,Cuw,Tuw" -i ${certificateFile} -d ${certDir}
done
You may find certutil in the libnss3-tools package (debian/ubuntu).
Source:
http://web.archive.org/web/20150622023251/http://www.computer42.org:80/xwiki-static/exported/DevNotes/xwiki.DevNotes.Firefox.html
See also:
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_certutil
The easiest way is to import the certificate into a sample firefox-profile and then copy the cert8.db to the users you want equip with the certificate.
First import the certificate by hand into the firefox profile of the sample-user. Then copy
/home/${USER}/.mozilla/firefox/${randomalphanum}.default/cert8.db (Linux/Unix)
%userprofile%\Application Data\Mozilla\Firefox\Profiles\%randomalphanum%.default\cert8.db (Windows)
into the users firefox-profiles. That's it. If you want to make sure, that new users get the certificate automatically, copy cert8.db to:
/etc/firefox-3.0/profile (Linux/Unix)
%programfiles%\firefox-installation-folder\defaults\profile (Windows)
Firefox now (since 58) uses a SQLite database cert9.db instead of legacy cert8.db.
I have made a fix to a solution presented here to make it work with new versions of Firefox:
certificateFile="MyCa.cert.pem"
certificateName="MyCA Name"
for certDB in $(find ~/.mozilla* ~/.thunderbird -name "cert9.db")
do
certDir=$(dirname ${certDB});
#log "mozilla certificate" "install '${certificateName}' in ${certDir}"
certutil -A -n "${certificateName}" -t "TCu,Cuw,Tuw" -i ${certificateFile} -d sql:${certDir}
done
Just wanted to add to an old thread to hopefully aid other people. I needed programmatically add a cert to the firefox database using a GPO, this was how I did it for Windows
1, First download and unzip the precompiled firefox NSS nss-3.13.5-nspr-4.9.1-compiled-x86.zip
2, Add the cert manually to firefox Options-->Advanced--Certificates-->Authorities-->Import
3, from the downloaded NSS package, run
certutil -L -d c:\users\[username]\appdata\roaming\mozilla\firefox\[profile].default
4, The above query will show you the certificate name and Trust Attributes e.g.
my company Ltd CT,C,C
5, Delete the certificate in step 2. Options-->Advanced--Certificates-->Authorities-->Delete
6, Create a powershell script using the information from step 4 as follows. This script will get the users profile path and add the certificate. This only works if the user has one firefox profile (need somehow to retrieve the users firefox folder profile name)
#Script adds Radius Certificate to independent Firefox certificate store since the browser does not use the Windows built in certificate store
#Get Firefox profile cert8.db file from users windows profile path
$ProfilePath = "C:\Users\" + $env:username + "\AppData\Roaming\Mozilla\Firefox\Profiles\"
$ProfilePath = $ProfilePath + (Get-ChildItem $ProfilePath | ForEach-Object { $_.Name }).ToString()
#Update firefox cert8.db file with Radius Certificate
certutil -A -n "UK my company" -t "CT,C,C" -i CertNameToAdd.crt -d $ProfilePath
7, Create GPO as a User Configuration to run the PowerShell script
Hope that helps save someone time
Recent versions of Firefox support a policies.json file that will be applied to all Firefox profiles.
For CA certificates, you have some options, here's one example, tested with Linux/Ubuntu where I already have system-wide CA certs in /usr/local/share/ca-certificates:
In /usr/lib/firefox/distribution/policies.json
{
"policies": {
"Certificates": {
"Install": [
"/usr/local/share/ca-certificates/my-custom-root-ca.crt"
]
}
}
}
Support for Thunderbird is on its way.
On Windows 7 with Firefox 10, the cert8.db file is stored at %userprofile%\AppData\Roaming\Mozilla\Firefox\Profiles\########.default\cert8.db. If you are an administrator, you can probably write a simple WMI application to copy the file to the User's respective folder.
Also, a solution that worked for me from http://www.appdeploy.com/messageboards/tm.asp?m=52532&mpage=1&key=&#52532
Copied CERTUTIL.EXE from the NSS zip file ( http://www.mozilla.org/projects/security/pki/nss/tools/ ) to C:\Temp\CertImport (I also placed the certificates I want to import there)
Copied all the dll's from the NSS zip file to C\:Windows\System32
Created a BAT file in %Appdata%\mozilla\firefox\profiles with this script...
Set FFProfdir=%Appdata%\mozilla\firefox\profiles
Set CERTDIR=C:\Temp\CertImport
DIR /A:D /B > "%Temp%\FFProfile.txt"
FOR /F "tokens=*" %%i in (%Temp%\FFProfile.txt) do (
CD /d "%FFProfDir%\%%i"
COPY cert8.db cert8.db.orig /y
For %%x in ("%CertDir%\Cert1.crt") do "%Certdir%\certutil.exe" -A -n "Cert1" -i "%%x" -t "TCu,TCu,TCu" -d .
For %%x in ("%CertDir%\Cert2.crt") do "%Certdir%\certutil.exe" -A -n "Cert2" -i "%%x" -t "TCu,TCu,TCu" -d .
)
DEL /f /q "%Temp%\FFProfile.txt"
Executed the BAT file with good results.
I was trying to achieve the same thing in Powershell and wrote a script to perform various functions that can be interactively selected. Of course, it's fairly easy to modify the script to automate certain things instead of provide options.
I'm an Infrastructure guy rather than a coder/programmer, so apologies if it's a bit cumbersome (but it does work!!).
Save the following as a PS1:
##################################################################################################
#
# NAME: RegisterFireFoxCertificates.ps1
#
# AUTHOR: Andy Pyne
#
# DATE : 22.07.2015
#
# COMMENT: To provide options for listing, adding, deleting and purging
# FireFox Certificates using Mozilla's NSS Util CertUtil
# Source: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/tools/NSS_Tools_certutil
#
# NOTE: You need a copy of the NSS Util CertUtil and it's associated dll's
# The specific files I used were:
#
# certutil.exe, fort32.dll, freebl3.dll, libnspr4.dll, libplc4.dll, libplds4.dll, nspr4.dll,
# nss3.dll, nssckbi.dll, nssdbm3.dll, nssutil3.dll, plc4.dll, plds4.dll, smime3.dll,
# softokn3.dll, sqlite3.dll, ssl3.dll, swft32.dll
#
##################################################################################################
##################################################################################################
# Setup a few parameters
$ErrorActionPreference = "Silentlycontinue"
$ExecutionPolicyOriginal = Get-ExecutionPolicy
$FireFoxExecutable = "C:\Program Files (x86)\Mozilla Firefox\Firefox.exe"
# This is the Firefox certificate database
$CertDB = "Cert8.db"
# The Certificate Nickname is a name you want to see on the certificates that you've imported in - so you know they were imported by this process
# However, when you look at the certificates in Firefox, they will be listed under whatever the certificate name was when it was generated
# So if your certificate is listed as 'Company123' when imported, it will still be called that as the Common Name, but when you click to view
# it, you will see that the first item in the Certificate Fields is what you 'nicknamed' it.
$CertificateNickname = "MyCompanyName FF AutoImport Cert"
# The Legacy Certificates are specific/explicit certificates which you wish to delete (The 'purge' option later in the script references these items)
$LegacyCertificates = #("OldCertificate1", "Company Cert XYZ", "Previous Company name", "Unwanted Certificate - 7", "123APTEST123")
# This is the list of databases / Firefox profiles on the machine
$FFDBList = #()
# Making sure our temporary directory is empty
$FFCertLocationLocal = "C:\FFCertTemp"
# The remote location of the certificates and
$FFCertLocationRemote = "\\myUNC\NETLOGON\FireFoxCert\"
# The local CertUtil executable (this is copied from the remote location above)
$FFCertTool = "$FFCertLocationLocal\CertUtil.exe"
# Making sure our temporary directory is empty
Remove-Item $FFCertLocationLocal -Recurse
New-Item -ItemType Directory -Path $FFCertLocationLocal
##################################################################################################
##################################################################################################
Clear
# We're going to get a list of the Firefox processes on the machine that are open and close them
# Otherwise the add/delete parts might not be successful with Firefox still running
$FireFoxRunningProcessesList = Get-Process | Where-Object {$_.Name -Match "FireFox"} | Select-Object ProcessName,Id | Format-Table -AutoSize
$FireFoxRunningProcesses = Get-Process | Where-Object {$_.Name -Match "FireFox"} | Select-Object -ExpandProperty Id
If (!$FireFoxRunningProcesses) {}
Else {
Write-Host "The following processes will be stopped to perform certificate manipulation:"
$FireFoxRunningProcessesList
$TerminateProcessQuestion = Read-Host "To auto-terminate (ungracefully!) processes, press 'Y', otherwise, press any other key"
If ($TerminateProcessQuestion -ne 'y') {
Clear
Write-Host "Cannot continue as Firefox process is still running, ending script ..."
Exit}
Else {ForEach ($FireFoxRunningProcess in $FireFoxRunningProcesses) {
[Int]$FireFoxRunningProcess = [Convert]::ToInt32($FireFoxRunningProcess, 10)
Stop-Process -Id $FireFoxRunningProcess -Force}}
}
##################################################################################################
##################################################################################################
# The remote files (certificates and the NSS Tools CertUtil files are copied locally)
$FFCertificateListItemRemote = Get-ChildItem $FFCertLocationRemote -Recurse -Include *.cer,*.dll,certutil.exe
ForEach ($FFCertificateItemRemote in $FFCertificateListItemRemote) {
Copy-Item $FFCertificateItemRemote.FullName -Destination $FFCertLocationLocal}
# Get a list of the local certificates
$FFCertificateListLocal = Get-ChildItem $FFCertLocationLocal -Recurse -filter *.cer
Clear
Set-ExecutionPolicy "Unrestricted"
# Find all Firefox profiles and create an array called FFDBList
# Of course, you'll only be able to get to the ones your permissions allow
$LocalProfiles = Get-ChildItem "C:\Users" | Select-Object -ExpandProperty FullName
ForEach ($LocalProfile in $LocalProfiles) {
$FFProfile = Get-ChildItem "$LocalProfile\AppData\Roaming\Mozilla\Firefox\Profiles" | Select-Object -ExpandProperty FullName
If (!$FFProfile) {Write-Host "There is no Firefox Profile for $LocalProfile"}
ELSE {$FFDBList += $FFProfile}
}
Clear
Write-Host "#################################"
Write-Host "The List of FireFox Profiles is:"
Write-Host "#################################"
$FFDBList
PAUSE
##################################################################################################
##################################################################################################
# Setup 4x functions (List, Delete, Add and Purge)
#
# - List will simply list certificates from the Firefox profiles
#
# - Delete will delete the certificates the same as the certificates you're going to add back in
# So for example, if you have 2x certificates copied earlier for import, 'CompanyA' and 'CompanyZ'
# then you can delete certificates with these names beforehand. This will prevent the
# certificates you want to import being skipped/duplicated because they already exist
#
# - Add will simply add the list of certificates you've copied locally
#
# - Purge will allow you to delete 'other' certificates that you've manually listed in the
# variable '$LegacyCertificates' at the top of the script
# Each of the functions perform the same 4x basic steps
#
# 1) Do the following 3x things for each of the Firefox profiles
# 2) Do the 2x following things for each of the certificates
# 3) Generate an expression using parameters based on the certificate nickname specified
# earlier, and the profile and certificate informaiton
# 4) Invoke the expression
Function ListCertificates {
Write-Host "#############################"
ForEach ($FFDBItem in $FFDBList) {
$FFCertificateListItemFull = $FFCertificateListItem.FullName
Write-Host "Listing Certificates for $FFDBitem"
$ExpressionToListCerts = "$FFCertTool -L -d `"$FFDBItem`""
Invoke-Expression $ExpressionToListCerts
}
PAUSE}
Function DeleteOldCertificates {
Write-Host "#############################"
ForEach ($FFDBItem in $FFDBList) {
ForEach ($FFCertificateListItem in $FFCertificateListLocal) {
$FFCertificateListItemFull = $FFCertificateListItem.FullName
Write-Host "Deleting Cert $FFCertificateListItem for $FFDBitem"
$ExpressionToDeleteCerts = "$FFCertTool -D -n `"$CertificateNickname`" -d `"$FFDBItem`""
Invoke-Expression $ExpressionToDeleteCerts
}}
PAUSE}
Function AddCertificates {
Write-Host "#############################"
ForEach ($FFDBItem in $FFDBList) {
ForEach ($FFCertificateListItem in $FFCertificateListLocal) {
$FFCertificateListItemFull = $FFCertificateListItem.FullName
Write-Host "Adding $FFCertificateListItem Cert for $FFDBitem"
$ExpressionToAddCerts = "$FFCertTool -A -n `"$CertificateNickname`" -t `"CT,C,C`" -d `"$FFDBItem`" -i `"$FFCertificateListItemFull`""
Write-Host $ExpressionToAddCerts
Invoke-Expression $ExpressionToAddCerts
#PAUSE
}}
PAUSE}
Function PurgeLegacyCertificates {
Write-Host "#############################"
ForEach ($FFDBItem in $FFDBList) {
ForEach ($LegacyCertificateItem in $LegacyCertificates) {
$LegacyCertificateItemFull = $LegacyCertificateItem.FullName
Write-Host "Purging Old Certs ($LegacyCertificateItem) for $FFDBitem"
#$ExpressionToDeleteLegacyCerts = "$FFCertTool -D -n `"$OldCertificate`" -d `"$FFDBItem`""
$ExpressionToDeleteLegacyCerts = "$FFCertTool -D -n `"$LegacyCertificateItem`" -d `"$FFDBItem`""
ForEach ($LegacyCertificate in $LegacyCertificates) {
Invoke-Expression $ExpressionToDeleteLegacyCerts}
}}
PAUSE}
##################################################################################################
##################################################################################################
# Creating a few options to invoke the various functions created above
$CertificateAction = ""
Function CertificateActionSelection {
Do {
Clear
$CertificateAction = Read-Host "Would you like to [L]ist all certificates [D]elete all old certificates, [A]dd new certificates, or [P]urge legacy certificates?"
} Until ($CertificateAction -eq "L" -or $CertificateAction -eq "D" -or $CertificateAction -eq "A" -or $CertificateAction -eq "P" )
If ($CertificateAction -eq "L") {ListCertificates}
If ($CertificateAction -eq "D") {DeleteOldCertificates}
If ($CertificateAction -eq "A") {AddCertificates}
If ($CertificateAction -eq "P") {PurgeLegacyCertificates}
}
Do {
Clear
$MoreCertificateActions = Read-Host "Would you like to [L]aunch Firefox (as $env:USERNAME), take a [C]ertificate action, or [Q]uit?"
If ($MoreCertificateActions -eq "L") {
Invoke-Item $FireFoxExecutable
Exit}
If ($MoreCertificateActions -eq "C") {CertificateActionSelection}
} Until ($MoreCertificateActions -eq "Q")
Remove-Item $FFCertLocationLocal -Recurse
Set-ExecutionPolicy $ExecutionPolicyOriginal
Exit
I had a similar issue on a client site where the client required a authority certificate to be installed automatically for 2000+ windows users.
I created the following .vbs script to import the certificate into the current logged on users firefox cert store.
The script needs to be put in the directory containing a working copy of certutil.exe (the nss version) but programatically determines the firefox profiles location.
Option Explicit
On error resume next
Const DEBUGGING = true
const SCRIPT_VERSION = 0.1
Const EVENTLOG_WARNING = 2
Const CERTUTIL_EXCUTABLE = "certutil.exe"
Const ForReading = 1
Dim strCertDirPath, strCertutil, files, slashPosition, dotPosition, strCmd, message
Dim file, filename, filePath, fileExtension
Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")
Dim objFilesystem : Set objFilesystem = CreateObject("Scripting.FileSystemObject")
Dim certificates : Set certificates = CreateObject("Scripting.Dictionary")
Dim objCertDir
Dim UserFirefoxDBDir
Dim UserFirefoxDir
Dim vAPPDATA
Dim objINIFile
Dim strNextLine,Tmppath,intLineFinder, NickName
vAPPDATA = WshShell.ExpandEnvironmentStrings("%APPDATA%")
strCertDirPath = WshShell.CurrentDirectory
strCertutil = strCertDirPath & "\" & CERTUTIL_EXCUTABLE
UserFirefoxDir = vAPPDATA & "\Mozilla\Firefox"
NickName = "Websense Proxy Cert"
Set objINIFile = objFilesystem.OpenTextFile( UserFireFoxDir & "\profiles.ini", ForReading)
Do Until objINIFile.AtEndOfStream
strNextLine = objINIFile.Readline
intLineFinder = InStr(strNextLine, "Path=")
If intLineFinder <> 0 Then
Tmppath = Split(strNextLine,"=")
UserFirefoxDBDir = UserFirefoxDir & "\" & replace(Tmppath(1),"/","\")
End If
Loop
objINIFile.Close
'output UserFirefoxDBDir
If objFilesystem.FolderExists(strCertDirPath) And objFilesystem.FileExists(strCertutil) Then
Set objCertDir = objFilesystem.GetFolder(strCertDirPath)
Set files = objCertDir.Files
For each file in files
slashPosition = InStrRev(file, "\")
dotPosition = InStrRev(file, ".")
fileExtension = Mid(file, dotPosition + 1)
filename = Mid(file, slashPosition + 1, dotPosition - slashPosition - 1)
If LCase(fileExtension) = "cer" Then
strCmd = chr(34) & strCertutil & chr(34) &" -A -a -n " & chr(34) & NickName & chr(34) & " -i " & chr(34) & file & chr(34) & " -t " & chr(34) & "TCu,TCu,TCu" & chr(34) & " -d " & chr(34) & UserFirefoxDBDir & chr(34)
'output(strCmd)
WshShell.Exec(strCmd)
End If
Next
WshShell.LogEvent EVENTLOG_WARNING, "Script: " & WScript.ScriptFullName & " - version:" & SCRIPT_VERSION & vbCrLf & vbCrLf & message
End If
function output(message)
If DEBUGGING Then
Wscript.echo message
End if
End function
Set WshShell = Nothing
Set objFilesystem = Nothing
I have an update of this awesome answer (just not working any more with last Firefox updates), in this same thread, made by H.-Dirk Schmitt, also thanks to the answer in this other thread made by BecarioEstrella.
I just adapted the script to recent changes.
Tested in 2021 just in Firefox 85.0.1 (64bit) in Ubuntu 20.04 and 18.04.
#!/usr/bin/env bash
function usage {
echo "Error: no certificate filename or name supplied."
echo "Usage: $ ./installcerts.sh <certname>.pem <Cert-DB-Name>"
exit 1
}
if [ -z "$1" ] || [ -z "$2" ]
then
usage
fi
certificate_file="$1"
certificate_name="$2"
for certDB in $(find ~/.mozilla* ~/.thunderbird -name "cert9.db")
do
cert_dir=$(dirname ${certDB});
echo "Mozilla Firefox certificate" "install '${certificate_name}' in ${cert_dir}"
certutil -A -n "${certificate_name}" -t "TCu,Cuw,Tuw" -i ${certificate_file} -d sql:"${cert_dir}"
done
If you want it just for Firefox, replace the line:
for certDB in $(find ~/.mozilla* ~/.thunderbird -name "cert9.db")
By
for certDB in $(find ~/.mozilla* -name "cert9.db")
Further readings:
NSS Shared DB
NSS Shared DB Howto

Resources