16

TL;DR

At the beginning of my script, I would like to check whether a file (given as a parameter) is overwritable, and quit if the current user does not have permission to do that.
(For example, if the user or the group he/she belongs to has been denied access for a file.)

The reason: in the script, I'm processing some data (which takes time), and at the end, I write the results into a file, but it would be a bit frustrating that the whole script ran correctly, but at the end, it turns out that the file is not writable (which I could have checked at the beginning).


What I tried

This is a correct way to test whether a file exists:

$Outfile = "w:\Temp\non-writable-file.txt"                # (normally I get this as a parameter)
$OutFileExists = Test-Path -Path $Outfile -PathType Leaf

Of course, $OutfileExists will be equal to True if the file exists.

But I would like to check whether this file is writable - now it's not (I changed the security settings myself to be able to test it):

Everyone - denied from writing

So, if I try this:

(Get-Acl $Outfile).Access

I get this output:

FileSystemRights  : Write
AccessControlType : Deny
IdentityReference : Everyone
IsInherited       : False
InheritanceFlags  : None
PropagationFlags  : None

FileSystemRights  : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : Everyone
IsInherited       : False
InheritanceFlags  : None
PropagationFlags  : None

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : DOESNTMATTER\Pete
IsInherited       : False
InheritanceFlags  : None
PropagationFlags  : None

(I could also have filtered this result.)
OK, now I know that the Everyone group has no write access.
But I still don't know how to check the overwritability of this file elegantly.

Sk8erPeter
  • 6,899
  • 9
  • 48
  • 67
  • If Everyone is denied write permissions, then no-one can write to the file without changing the permissions. "Deny entries take precedence over allow entries. This means that if a user is a member of two groups, one that is allowed a permission and another that is denied the same permission, the user is denied that permission." – bob Apr 08 '14 at 17:02
  • 2
    @bob: I know that and I didn't ask WHY I can not overwrite the file (I changed the security settings myself for being able to test it!!), I asked HOW I could check (in PowerShell) whether a file is writable. – Sk8erPeter Apr 08 '14 at 17:33

2 Answers2

28

I've used this:

Try { [io.file]::OpenWrite($outfile).close() }
 Catch { Write-Warning "Unable to write to output file $outfile" }

It will attempt to open the file for write access, then immediately close it (without actually writing anything to the file). If it can't open the file for any reason, it will run the Catch block, and you can do your error handling there.

weir
  • 4,521
  • 2
  • 29
  • 42
mjolinor
  • 66,130
  • 7
  • 114
  • 135
  • 2
    great answer. for those wondering, in addition to not writing anything to the file, this also does not delete the file and also does not modify its 'LastWriteTime'. – orion elenzil Jun 17 '21 at 17:03
1

You could attempt a quick write (append) to the file such as

"" | Out-File 'w:\Temp\non-writable-file.txt' -Append

Where no write permissions exist you will receive an error:

Out-File : Access to the path 'w:\Temp\non-writable-file.txt' is denied.
...
+ CategoryInfo : OpenError: (:) [Out-File], UnauthorizedAccessException
+ FullyQualifiedErrorId : FileOpenFailure,Microsoft.PowerShell.Commands.OutFileCommand

You could catch and terminate on that error, in the case where write permission exists - you've just appended a new line to the file.

bob
  • 983
  • 11
  • 21