unlock a locked file

Hello

I know that I may ask the Finder to unlock a locked file with :

tell application "Finder"
		set locked of item hfsPath to false -- Déverrouille le fichier/dossier
	end tell

But as I continue to do my best to get rid of the Finder, I’m wondering if this may be done without using the Finder.

I looked in Xcode but it seems that the locked status isn’t reachable thru ASObjC.
Am I wrong ?

Yvan KOENIG running El Capitan 10.11.6 in French (VALLAURIS, France) vendredi 16 septembre 2016 12:47:48

Got it.

I must trigger NSURLIsUserImmutableKey.

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

on unlockThat:HfsPath
	set theURL to current application's class "NSURL"'s fileURLWithPath:(POSIX path of HfsPath)
	set {theResult, theError} to theURL's setResourceValue:(false) forKey:(current application's NSURLIsUserImmutableKey) |error|:(reference)
end unlockThat:

set aFile to choose file "Please, select a locked one !"

tell application "Finder"
	set lockedBefore to locked of aFile
end tell

my unlockThat:aFile

tell application "Finder"
	set lockedAfter to locked of aFile
end tell

{lockedBefore, lockedAfter}

Yvan KOENIG running El Capitan 10.11.6 in French (VALLAURIS, France) vendredi 16 septembre 2016 14:46:00

Here is an easier way using do shell script

This will unlock the file

do shell script "chflags nouchg " & POSIX path of hfsPath

This will lock the file

do shell script "chflags uchg " & POSIX path of hfsPath

It might be easier in the sense of less typing (although it really needs a quoted form of in there), but it’s a heck of lot slower to run.

I put these two scripts in Script Geek to compare:

set aFile to alias "Macintosh HD:Users:shane:Desktop:Screen Shot 2016-09-17 at 2.18.36 PM.png"

do shell script "chflags uchg " & quoted form of POSIX path of aFile
do shell script "chflags nouchg " & quoted form of POSIX path of aFile

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

on unlockThat:HfsPath
	set theURL to current application's class "NSURL"'s fileURLWithPath:(POSIX path of HfsPath)
	set {theResult, theError} to theURL's setResourceValue:(false) forKey:(current application's NSURLIsUserImmutableKey) |error|:(reference)
end unlockThat:

on lockThat:HfsPath
	set theURL to current application's class "NSURL"'s fileURLWithPath:(POSIX path of HfsPath)
	set {theResult, theError} to theURL's setResourceValue:(true) forKey:(current application's NSURLIsUserImmutableKey) |error|:(reference)
end lockThat:

set aFile to alias "Macintosh HD:Users:shane:Desktop:Screen Shot 2016-09-17 at 2.18.36 PM.png"
my unlockThat:aFile
my lockThat:aFile

When I set them to be run 100 times, the shell script version takes on average more than 70 times as long.

In fact, when I compare the shell script version with the Finder:

set aFile to alias "Macintosh HD:Users:shane:Desktop:Screen Shot 2016-09-17 at 2.18.36 PM.png"
tell application "Finder"
	set locked of aFile to true
	set locked of aFile to false
end tell

the Finder is nearly 10 times faster.

Speed isn’t everything, but if something’s that much slower than the Finder, it’s not a good look :wink:

FYI, if you’re not going to check the result or do anything with the error, it’s a fraction simpler just to use:

theURL's setResourceValue:(false) forKey:(current application's NSURLIsUserImmutableKey) |error|:(missing value)

Thanks Shane.
I will not try to spare the time required to send the three values to the script.
At this time I don’t use them but one never knows.

Yvan KOENIG running El Capitan 10.11.6 in French (VALLAURIS, France) samedi 17 septembre 2016 09:40:34

There’s no need to pass them. If you think there could be an error, you could use this:

on unlockThat:HfsPath
	set theURL to current application's class "NSURL"'s fileURLWithPath:(POSIX path of HfsPath)
	set {theResult, theError} to theURL's setResourceValue:(false) forKey:(current application's NSURLIsUserImmutableKey) |error|:(reference)
	if not theResult as boolean then
		error (theError's |localizedDescription|() as text)
	end if
end unlockThat:

Oops

It seems that my wording was wrong.

The original instruction was :

set {theResult, theError} to theURL's setResourceValue:(false) forKey:(current application's NSURLIsUserImmutableKey) |error|:(reference)

Your proposal was :

theURL's setResourceValue:(false) forKey:(current application's NSURLIsUserImmutableKey) |error|:(missing value)

I wanted to say that I had no need to grab the values « set {theResult, theError} to »

I don’t know why I wrote about three values when they are only true.

But the worse thing is that I missed that the last parameter used in the instruction changed from (reference) to (missing value) which is why « set {theResult, theError} to » become unneeded
.

Yvan KOENIG running El Capitan 10.11.6 in French (VALLAURIS, France) samedi 17 septembre 2016 15:41:13