Code Monkey home page Code Monkey logo

ps-sfta's People

Contributors

craysiii avatar danyfirex avatar larpico avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ps-sfta's Issues

Set-FTA flashes all icons on the desktop.

Hi, This project has been very useful for our team, so thank you sharing.

We had various customers on Azure Virtual Desktop reporting that their screen constantly flashes each time Set-FTA is run. To limit the flashing, we altered the code to within Set-FTA to only execute if it differs by using Get-FTA which is significantly quicker as well when using the measure-command.

Not sure if it breaks it for any other functions as we don't use all functionality but thought I might share it if its useful.


#### Set-FTA causes flashes of icons on the desktop when it executed. Get-FTA does not have this problem
#### Get-FTA takes 5-10ms. Set-FTA takes 500ms.

function Set-FTA {

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [String]
    $ProgId,

    [Parameter(Mandatory = $true)]
    [Alias("Protocol")]
    [String]
    $Extension,
      
    [String]
    $Icon
  )
  
  if (Test-Path -Path $ProgId) {
    $ProgId = "SFTA." + [System.IO.Path]::GetFileNameWithoutExtension($ProgId).replace(" ", "") + $Extension
  }

  Write-Verbose "ProgId: $ProgId"
  Write-Verbose "Extension/Protocol: $Extension"

  #### START NEW CODE
  try {
    if ((Get-FTA -Extension $Extension -ErrorAction Stop) -eq $ProgId) { 
        Write-Verbose "Extension $Extension is already set to $ProgId"
        return 
    }
    else {
        Write-Output "Extension $Extension required to be set to $ProgId"
    }
  } 
  catch {
    Write-Verbose "Unable to determine Get-FTA on SET-FTA "
  }
  #### END NEW CODE

  function local:Update-RegistryChanges {
    $code = @'
    [System.Runtime.InteropServices.DllImport("Shell32.dll")] 
    private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
    public static void Refresh() {
        SHChangeNotify(0x8000000, 0, IntPtr.Zero, IntPtr.Zero);    
    }
'@ 

    try {
      Add-Type -MemberDefinition $code -Namespace SHChange -Name Notify
    }
    catch {}

    try {
      [SHChange.Notify]::Refresh()
    }
    catch {} 
  }


##### TRUNCATED

"Sometimes" the HTTPS protocol set by the {Set-PTA ChromeHTML https} command gets deleted by SystemSettings.exe when it opens!

For some reason Win11's Settings app's Default Apps/Google Chrome Page doesn't like the HTTPS settings generated from the script every the time.

The association works if we use it but when we open the Settings app to confirm their assignment, more like the Schrödinger's cat, sometimes HTTPS gets deleted right away as if it doesn't like the hash that was generated for it. Don't have this issue with .htm, .html, .pdf, or http.
image

To work around it, I open the Settings app to its Chrome page earlier in the script and then run the Set-PTA command in a loop with a few seconds wait till Get-PTA confirms that the setting is stuck for good. It seems to work, but it's clunky and intrusive when System Settings pops up in the middle of a background running script. It also slows down the deployment because each loop needs about 15 seconds for everything to settle in.

As the Process Monitor shows here, I set http and it was fine but https had to go through the loop 4 times before SystemSettings.exe leaves it alone.
image

Any help fixing this is greatly appreciated.

Thank you,
@-

Suggestion: Use alternative approach for obtaining the user SID

Hey there folks, firstly thank you so SO much for writing this and making it open source!!! 😄

I notice that Set-FTA was quite slow on my system:

e.g.

C:\Users\Fots\Downloads> Measure-Command { Set-FTA -ProgId foobar2000.WAV -Extension .wav -Verbose }
VERBOSE: ProgId: foobar2000.WAV
VERBOSE: Extension/Protocol: .wav
VERBOSE: Getting Hash For foobar2000.WAV   .wav
VERBOSE: baseInfo: .wavs-1-5-21-4006214458-3003202-965951313-1001foobar2000.wav01d83c0f87537800user choice set via windows user experience {d18b6dd5-6124-4341-9318-804003bafa0b}
VERBOSE: Hash: K+RBO0qUSjg=
VERBOSE: Write Registry Extension: .wav
VERBOSE: Remove Extension UserChoice Key If Exist: Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.wav\UserChoice
VERBOSE: Write Reg Extension UserChoice OK

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 4
Milliseconds      : 805
Ticks             : 48050688
TotalDays         : 5.56142222222222E-05
TotalHours        : 0.00133474133333333
TotalMinutes      : 0.08008448
TotalSeconds      : 4.8050688
TotalMilliseconds : 4805.0688

After some investigation, I found that the local Get-UserSid was the main cause of delay. I have always used another approach to obtain the Sid which is shown below:

    $userSid = ([System.Security.Principal.WindowsIdentity]::GetCurrent()).User.Value.ToLower()

Switching to this approach, I now see a significant improvement in performance:

C:\Users\Fots\Downloads> Measure-Command { Set-FTA -ProgId foobar2000.WAV -Extension .wav -Verbose }
VERBOSE: ProgId: foobar2000.WAV
VERBOSE: Extension/Protocol: .wav
VERBOSE: Getting Hash For foobar2000.WAV   .wav
VERBOSE: baseInfo: .wavs-1-5-21-4006214458-3003202-965951313-1001foobar2000.wav01d83c0fceda0400user choice set via windows user experience {d18b6dd5-6124-4341-9318-804003bafa0b}
VERBOSE: Hash: Et6Y8vcr12U=
VERBOSE: Write Registry Extension: .wav
VERBOSE: Remove Extension UserChoice Key If Exist: Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.wav\UserChoice
VERBOSE: Write Reg Extension UserChoice OK

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 242
Ticks             : 2422168
TotalDays         : 2.80343518518519E-06
TotalHours        : 6.72824444444444E-05
TotalMinutes      : 0.00403694666666667
TotalSeconds      : 0.2422168
TotalMilliseconds : 242.2168

Just wanted to share this in case you wish to update the script for everyone.

Thanks heaps
Fotis

Select an app to open this . file prompt

I have always noticed that even after setting default association for an app using the script, when opening any file for first time, it still always prompts me to select an app to open the file

For instance, i have set .txt files to be opened by sublime text by default but i still get the prompt as evident from my screenshot attached below, is this normal ?
Register-FTA "C:\Program Files\Sublime Text\sublime_text.exe" ".txt"

image

Cleanup $allApplicationAssociationToasts handling

Issues:

  1. The code that first initializes $allApplicationAssociationToasts will cause $allApplicationAssociationToasts to be a string, rather than an array, if the original call returns 1 result. This leads to the resultant buildup of a string, not an array, by the subsequent calls, which isn't right.

  2. While fixing this, I rewrote portions of $allApplicationAssociationToasts to be (at least in my opinion) easier to read and troubleshoot. I believe it is functionally identical, however YMMV.

Tested on Powershell 7 w/ StrictMode -Version 3

Submitting my proposed changes back. Sorry that this is just raw code, not a diff. I can convert to diff if desired.


$allApplicationAssociationToasts = @(
  Get-Item -Path HKLM:\SOFTWARE\Classes\$Extension\OpenWithList\* -ErrorAction SilentlyContinue | ForEach-Object {
    "Applications\$($_.PSChildName)"
  })

$allApplicationAssociationToasts += @(
  Get-Item -Path HKLM:\SOFTWARE\Classes\$Extension\OpenWithProgids -ErrorAction SilentlyContinue | ForEach-Object {
    $_.Property | Where-Object { $_ -and $_ -ne "(default)" }
  })

$allApplicationAssociationToasts += @(
  Get-Item -Path HKLM:\SOFTWARE\Clients\StartMenuInternet\*\Capabilities\* , HKCU:\SOFTWARE\Clients\StartMenuInternet\*\Capabilities\* -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -in "URLAssociations", "FileAssociations" } | ForEach-Object {
    if ($_.Property -contains $Extension) {
      Get-ItemPropertyValue -Path $_.PSPath -Name $Extension
    }
  })

$allApplicationAssociationToasts | Where-Object { $_ } | ForEach-Object {
  if (Set-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\ApplicationAssociationToasts -Name "$($_)_$($Extension)" -Value 0 -Type DWord -ErrorAction SilentlyContinue -PassThru) {
    Write-Verbose  ("Write Reg ApplicationAssociationToastsList OK: " + $_ + "_" + $Extension)
  }
  else {
    Write-Verbose  ("Write Reg ApplicationAssociationToastsList FAILED: " + $_ + "_" + $Extension)
  }
}

Issues on 21H2

We are desperately trying to get Adobe Reader to be the default application for PDF files (rather than Edge). Currently on Windows 10 21H2, the FTA keeps getting reset to MSEdgePDF no matter what I do.

Commands:

PS C:\windows\system32> Get-FTA .pdf
MSEdgePDF

PS C:\windows\system32> Remove-FTA MSEdgePDF .pdf
Removed: MSEdgePDF

PS C:\windows\system32> Get-FTA .pdf

PS C:\windows\system32> Set-FTA AcroExch.Document.DC .pdf

PS C:\windows\system32> Get-FTA .pdf
MSEdgePDF

PS C:\windows\system32>

What am I missing?

Error Logging

Hi,

We run set-fta on user logins using a powershell logon script. We also capture the errors at the end of the script in the $error variable for review. I noticed there's a lot around set-fta functions and wondering if they are expected?

Some examples are below. I'm not skilled enough to work out exactly what it is doing (not even sure why .tmp files would be used)?

at local:Remove-UserChoiceKey, scriptlocation\User-Functions.ps1: line 632 - Unable to find type [Registry.Utils].
at local:Update-RegistryChanges, scriptlocation\User-Functions.ps1: line 552 - Unable to find type [SHChange.Notify].
at local:Remove-UserChoiceKey, scriptlocation\User-Functions.ps1: line 627 - Could not find a part of the path 'C:\Users\local_USERNAME\Temp\ne5j4dla.tmp'.
at local:Update-RegistryChanges, scriptlocation\User-Functions.ps1: line 547 - Could not find a part of the path 'C:\Users\local_USERNAME\Temp\gqq3cmu1.tmp'.

Apologies if this is out of scope, please delete the issue if it is.

Set association for multiple extensions using a foreach loop/my own variable: NO WAY!

I'm tryin' to modify multiple files associations in one go like below (NOTA : VLC is already installed):

sl "I:\PS-SFTA-master"

. .\SFTA.ps1

$MediaExtensions = @(".3g2", ".3gp", ".3gp2")

foreach ($MediaExtension in $MediaExtensions){
    if((Get-FTA $MediaExtension) -ne 'VLC$MediaExtension.Document)'){ Set-FTA 'VLC$MediaExtension.Document' '$MediaExtension' -Verbose }

    Write-Host "=========================================="
    Get-FTA $MediaExtension -Verbose
    Write-Host ""
}


VERBOSE: ProgId: VLC$MediaExtension.Document
VERBOSE: Extension/Protocol: $MediaExtension
VERBOSE: Write Registry Protocol: $MediaExtension
VERBOSE: Remove Protocol UserChoice Key If Exist: HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$MediaExtension\UserChoice
VERBOSE: Write Reg Protocol UserChoice OK
==========================================
VERBOSE: Get File Type Association for .3g2
WMP11.AssocFile.3G2


VERBOSE: ProgId: VLC$MediaExtension.Document
VERBOSE: Extension/Protocol: $MediaExtension
VERBOSE: Write Registry Protocol: $MediaExtension
VERBOSE: Remove Protocol UserChoice Key If Exist: HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$MediaExtension\UserChoice
VERBOSE: Write Reg Protocol UserChoice OK
==========================================
VERBOSE: Get File Type Association for .3gp
WMP11.AssocFile.3GP


VERBOSE: ProgId: VLC$MediaExtension.Document
VERBOSE: Extension/Protocol: $MediaExtension
VERBOSE: Write Registry Protocol: $MediaExtension
VERBOSE: Remove Protocol UserChoice Key If Exist: HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$MediaExtension\UserChoice
VERBOSE: Write Reg Protocol UserChoice OK
==========================================
VERBOSE: Get File Type Association for .3gp2
WMP11.AssocFile.3G2
$MediaExtension = ".3g2"

if((Get-FTA $MediaExtension) -ne 'VLC$MediaExtension.Document'){ Set-FTA 'VLC$MediaExtension.Document' '$MediaExtension' -Verbose }
Write-Host "=========================================="
Get-FTA $MediaExtension -Verbose


VERBOSE: ProgId: VLC$MediaExtension.Document
VERBOSE: Extension/Protocol: $MediaExtension
VERBOSE: Write Registry Protocol: $MediaExtension
VERBOSE: Remove Protocol UserChoice Key If Exist: HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$MediaExtension\UserChoice
VERBOSE: Write Reg Protocol UserChoice OK
==========================================
VERBOSE: Get File Type Association for .3g2
WMP11.AssocFile.3G2

Function Set-FTA seems to not read/convert my custom variable ($MediaExtension) correctly

================================================================

But all things go well with one extension at the time :

Set-FTA 'VLC.3g2.Document' '.3g2' -Verbose

VERBOSE: ProgId: VLC.3g2.Document
VERBOSE: Extension/Protocol: .3g2
VERBOSE: Write Registry Extension: .3g2
VERBOSE: Remove Extension UserChoice Key If Exist: Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.3g2\UserChoice
VERBOSE: Write Reg Extension UserChoice OK

Your help will be appreciated. Thanx

PS : Unecessary verbose output have been removed

Convert-Int32 sometimes performs the wrong conversion, due to a Double coming in

The $Value parameter on Convert-Int32 will sometimes come in as a Double. When this occurs, the conversion performed will be incorrect and the wrong value is returned.

This is due to an Int32 overflowing into a Double instead of an Int64. The behavior can be seen here:

Write-Host (([int]::MaxValue + 1) -is [double]) (([int]::MaxValue + 1) -is [long])

I think that just adding a [long] type to the $Value parameter will be sufficient to fix this. Wherever the original Int32 overflow arithmetic is occurring could also be fixed to use Int64 arithmetic, but I'm guessing the overflow will never be large enough that the Double to Int64 conversion becomes lossy.

Set-PTA - Error Thrown - Write Reg Protocol UserChoice FAILED

Downloaded script.
Imported functions into powershell session.
Tried to set chrome as default browser using "Set-PTA ChromeHTML http".
Error is thrown "Write Reg Protocol UserChoice FAILED".
Chrome is not the default.

OS: Windows 10 22h2 (19045.4123)
Powershell: 5.1.19041.4123
image

Chrome can be selected by Windows Default Apps control panel.

Any assistance would be greatly appreciated. Thank you.

Change registry values for different user

Hi,

Is it possible to change the registry entries for a different user than the script was started from?

If I change the registry values in the script with them from the specific user SID, it doesn't work.

I hope I post this in the right category here.

Thanks

Does not change file associations

I'm not sure if I'm using this incorrectly, but when I attempt the following:

import-module .\SFTA.ps1
Set-FTA "C:\Program Files\JPEGView64\JPEGView.exe" .gif

Windows Explorer refreshes, but then the file type association remains unchanged (the .gif file still opens with Internet Explorer, rather than JPEGView). Am I doing something wrong?

I'm on Windows 10 version 1607 (LTSC 2016).

Acrobat 64-Bit

This worked great for making the 32-bit version of Acrobat Reader the default for PDFs but Acrobat Reader updated to the 64-Bit and this no longer works.

Any ideas how to make the 64-bit version the default?

Register-FTA throws an error when StrictMode enabled

Windows 11 build 22000
PSVersion 5.1.22000.65
PS-SFTA 1.2.0

A simple example to reproduce the error:

Set-ExecutionPolicy -Scope Process Bypass
Set-StrictMode -Version Latest
. .\SFTA.ps1
Register-FTA "$Env:SystemRoot\System32\notepad.exe" .ps1

Register-FTA throws the following error:

The property '.ps1' cannot be found on this object. Verify that the property exists.
At C:\Users\User\Desktop\SFTA.ps1:333 char:27
+     (Get-ItemProperty ("$($_.PSPath)\Capabilities\" + (@("URLAssociat ...
+                           ~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], PropertyNotFoundException
    + FullyQualifiedErrorId : PropertyNotFoundStrict

Thanks!

Sorry to clutter the issues with a non-issue but wanted to say thanks for putting this together. I was making headway using procmon to monitor the registry but the stupid hashing algorithm would have taken forever to figure out. Every time I have the need to programmatically set a file extension in windows its like starting all over again. Surely Microsoft could find a way to prevent hijacking without making it impossible to do programmatically in a non-hacky way.

Anyways, thanks!

IndexOf

Hello,

I'm trying to change .txt association.
I want to set notepad++ as default. BTW I tried with notepad and get same error.
My error is the following one :

Exception calling "IndexOf" with "2" argument(s): "Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: startIndex"
At \NetworkPath\SFTA.ps1:523 char:5

  • $position2 = $dataString.IndexOf("}", $position1)
    
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    • FullyQualifiedErrorId : ArgumentOutOfRangeException

Exception calling "Substring" with "2" argument(s): "StartIndex cannot be less than zero.
Parameter name: startIndex"
At \NetworkPath\SFTA.ps1:525 char:5

  • Write-Output $dataString.Substring($position1, $position2 - $posi ...
    
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    • FullyQualifiedErrorId : ArgumentOutOfRangeException

I use the following command :
Register-FTA "C:\Program Files (x86)\Notepad++\notepad++.exe" .txt -Icon "C:\Program Files (x86)\Notepad++\notepad++.exe"
or
Register-FTA "C:\Windows\notepad.exe" .txt -Icon "C:\Windows\notepad.exe"

Can you help me with this ?

Regards

Robin

Get-PTA don't seem to work

Hi,

I register FTP protocole with Brave and from the return it seem to work BUT when I go in the settings App to confirm that Brave is now handling the FTP protocol there is no application assigned to the FTP protocol ?

Note: It's also the same with others protocols I try to assign to Brave browser.

image

Is it a bug or I do something wrong ? 🤔

Regards :octocat:

Change between Windows Release 1909 and 2009

Do you happen to know if something has changed in Windows between Release 1909 (Build 18363) and 2009 (Build 19042)? The script changes an association perfectly on 1909, but doesn't succeed in 2009 (yet without error message).

"SFTA." prepended unintentionally to ProgId

This might be a very niche case, but it actually happened to me.

I tried to register VSCode for Powershell files (.ps1) and kept getting ProgId SFTA.VSCode.ps1 as UserChoice, instead of VSCode.ps1. After some investigation in the code, I realized that this happened because, ironically, my script was named vscode.ps1. PS-SFTA checked for the existence of a file of that name and thus prepended SFTA..

I don't know whether this should be fixed or not but it took me some time to figure out the strange behavior. In the end, it's quite funny, I must admit.

Question ?

First thanks for this scripts ! 👍

Could you explain to me what is the difference between Set-FTA and Register-FTA ? 🤔

Could I always use Regsiter-FTA with the path of the program instead of using Set-FTA with the program ID since are hard to find when program are not associated already with an extension ?

It's not clear to me the difference between the two, some simple exemples when to use them would help me a lot.

One last question: With Set-PTA could I use a path instead of a program-ID ?

Best Regards ! :octocat:

Put it on PSGallery

Would you be mad if I put the script on PSGallery?
Then It could be installed with Install-Script -Name SFTA

Commands Aren't Recognized

When I try to run the script and then running any of the commands, it doesn't recognize any of them. I've ran into errors before, but that was just about the policy thing which I bypassed using a powershell command.

No system-wide defaults set

We are using this script embedded into our own script for deployments, and so far it works, when we run it in user context.
However, so far, we are unable to change the File Associations systemwide for all users.
Is there a way to achieve this or is this script "just not made" for this type of usage?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.