PowerShell UnauthorizedAccessException writing file on network share - windows

I'm trying to write a PowerShell script which minifies a directory full of .js files on the webserver. The files belong to me; I created it; I'm logged in as me. I can open and save the files in a text editor or via a batch file. The PowerShell script thinks it's operating as me ($env:username), and I'm running it from a PowerShell console that I ran with "Run As Administrator".
The loop looks like this. $files is confirmed to be a collection of file objects representing the files I want.
$tool = "c:\Program Files (x86)\Microsoft\Microsoft Ajax Minifier\ajaxmin.exe";
foreach($ofile in $files) {
$outfile = $ofile.DirectoryName + "\" + $ofile.BaseName + ".min.js";
& $tool $ofile.FullName > $outfile;
}
I get the following error on each file:
Access to the path '\\webserver\inetpub\whatever\js\validation.min.js' is denied.
At C:\minifyall.ps1:18 char:27
+ & $tool $ofile.FullName > <<<< $outfile;
+ CategoryInfo : OpenError: (:) [], UnauthorizedAccessException
+ FullyQualifiedErrorId : FileOpenFailure
The file there is the file it ought to be writing to, and get-acl tells me I have Allow FullControl. It can read the non-.min files just fine.
If I change the output directory to the current working directory (on my own machine), the script works as expected:
# No prob
$outfile = $ofile.BaseName + ".min.js";
Is there something else I need to do to enable this script to write to remote files? Other than rewriting it in Perl (Update: In the end, I rewrote it in Perl and as of February 2020 have had no trouble with it. This is not an endorsement of Perl).
Tips on PowerShell coding style are welcome too. My professional experience with PowerShell began approximately an hour after breakfast today.

Try and print all the full paths in order to see there isn't anything funny going on.
Another a reason could be that, since the target files are Javascript, some security system prevents access. Are you running an antivirus?
If all else fails, use Procmon to see what exactly is going on on the filesystem.

Keep in mind that file ACLs on the remote machine that grant you permission isn't enough. You also need permission to write on the share. Go to the remote machine, right click the folder, go to the Sharing tab, Advanced Sharing and click the Permissions button. Check those permissions to make sure you have write privileges.

Related

Change Windows File permissions in Lua to allow writing

I am reading and then modifying some data in a file that is located in the Windows program files folder.
Because of this the file does not have write permissions. So I receive an error when trying to write to it.
When manually giving write permissions to the folder containing the file, the script will work.
Is it possible to modify a folders permissions within a Lua script, or write to a file regardless of it's permissions? Or can this only be done manually from the File Explorer?
This is my current section of code that is re-writing the inputFile:
k=0
updatefile = io.open(inputFile,"w")
for k=1,i do
updatefile:write(modfilecontent[k] .. '\n') --This is where I'm blocked by permissions
end
updatefile:close()
Also if there is a solution possible, and I load this script onto another persons computer that does not have admin privileges would the solution still work?
EDIT:
Piglet's solution will work using the os.execute method to change privileges.
As long as the software, that the plug-in is being used in, is ran as admin the first time the permissions will be set. From then on you no longer need to run as admin.
Below is the code that I needed to add to the beginning of the program, minus the brackets of course
os.execute('icacls "C:\\Program Files\\[software name]\\[folder name]" /grant Everyone:(OI)(CI)F /T')
You could use os.execute to run the appropriate Windows command.
See How to grant permission to users for a directory using command line in Windows?
Alternatively use a library that supports stuff like this. Maybe checkout
https://keplerproject.github.io/luafilesystem/manual.html
Also if there is a solution possible, and I load this script onto
another persons computer that does not have admin privileges would the
solution still work?
As that person wouldn't be able to run Lua as administrator that is very unlikely. That would completly defy the purpose of different user levels.

0KB PowerPoint file on File Share Server: identify/delete

I'm using Windows 7 with a VPN (Cisco AnyConnect) connection to an academic file share server. I copied a PowerPoint file from a local path to the server, and tried to delete the file on the server after no longer needing it.
It now shows up as a 0KB file, and I can no longer perform any actions on it except opening it as read-only. When I do open it as read-only, I receive the prompt "Unknown is working on \server\share_pathtofile. Do you want to open a read-only copy in the meantime?", and the file is empty (no slides, settings, etc). Here 'server_pathtofile' is the entire path of the problem file. I am positive no other user is accessing the file from another machine.
I have tried to overwrite it by Save As, using the same file name. Once I click Save, the save window closes and reopens without performing any action. This happens indefinitely if I continue to click Save. I can save the file with a different name on the server, and delete the file with a different name without issue.
I tried removing problem file using python through the Anaconda Spyder distro i use on my laptop.
import os
path = r"\\server\share"
file = r"\file.pptx"
#file = r"\test2.txt"
f = path + file
os.remove(f)
When i run it for the trouble file, it produces the error:
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: '\\\\server\share_pathtofile'
I looked into the shutil function, but don't think that'll be any more useful. I suspect the process handle for the PowerPoint file has been corrupted in some way. I thought to try and use Windows to perform the action directly through Powershell:
Remove-Item 'file.pptx'
But received a similar error:
Remove-Item : Cannot remove item \\server\share_pathtofile: The process cannot access the file '\\server\share_pathtofile' because it is being used by another
process.
At line:1 char:12
+ Remove-Item <<<< 'file.pptx'
+ CategoryInfo : WriteError: (\\server...file.pptx:FileInfo) [Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
UPDATE 1: I tired postanote's suggestion by deleting through cmd.exe
pushd \\server\share
del /f "file.pptx"
The process cannot access the file because it is being used by another process.
I would've thought my inclusion of the powershell attempt to remove the file would've made this approach an obvious dead end. Shoudln't i be trying to find the so-called process that is telling Windows the file is still open?
Also, I was able to reproduce the same issue with a second ppt file and an excel file. They are not 0KB, but upon opening i get the same sort of prompt: "someone else is working on them and you can read-only".
I was making copies of the file within the same folder directory of the file share. My connection to the server got interrupted somehow, as Windows Explorer prompted me saying the connection to server share was able to be found. Upon closing the prompt, Windows Explorer did an unexpected refresh, the mapped drive was fine (i could navigate it without having to remap it), then suddenly I had two more problem files.
It is certainly not having the Windows Explorer preview pane open, i have never used that Explorer feature. Any ideas? We shouldn't let this file win...
PE will only look at process where it was started. Just like Task Manager, and if you are not accessing the file via some process (PowerPoint.exe), or know that in a shared file scenario, no one else has it locked, then you can take action on it.
This is not a PS specific issue (so not really a PS question) or anything related to process explorer and nothing to do with admin right on a server/workstation. If you have read/write/modify/delete permissions on a system / file share, you can act on that file of course.
It's a Windows proper issue. I've seen (and had this happen) this zero length files (depending on how they were created / copied) more than once, and they appear as impossible to delete.
The deal here, often Windows Explorer for such files won't even let you shorten the name via a rename effort. So, name length, odd characters, etc., are often the culprit(s)
So, you need to use cmd.exe and delete the file using the short DOS name. Just do a dir on the location where file is to get the short name and delete it.
dir /X

what is the best practice for Perl getting parent folder permissions while running on windows

I'm not much of a Perl developer but I need it to make triggers for perforce.
So this is the background:
I have a windows service that runs as admin that calls the Perl script on windows.
The script needs to create a file on a network storage which is both configured to work with windows and UNIX permissions\security types.
Since the user that is running the script is an admin user all folders and files that it creates under all directories are no inheriting the directories permissions but makes it editable only to root.
What I try to do is create the file and than chmod it to the parent folder's "stat" results.
my ($perms, $uid, $gid) = (stat $ParentDirFullPath)[2, 4, 5];
$perms = sprintf("%04o", $perms & 0777);
chmod($perms, $NewFileFullPath);
The problem is that stat command on windows dosen't get the unix\gid and unix\uid + the chmod command is not really supported.
I looked into the file::stat module to find a way for displaying windows permissions(since they are present there too) to take them and apply them with a command that I didn't test yet that should be probably under the module Win32::FileSecurity.
I didn't find a way to get the permissions from there(I get stat=ARRAY(0x46d0f8)).
Any ideas or suggestions?
TL;DR:("How to?" question) Running Perl script on windows that takes parent folder permissions and applies them on a file that the scripts creates in the network storage that supports both Windows and Unix security/permissions types(the permissions that I want to apply are windows like permissions for groups and users).
Edit:
I tried the next code:
use Win32::FileSecurity qw(Get EnumerateRights);
use Win32;
my $dir1 = "\\\\NetworkStorage\\home\\user1";
my $dir2 = "\\\\NetworkStorage\\home\\user1\\PerlFileSecTest";
my %permissions;
Win32::FileSecurity::Get($dir1, \%permissions);
Win32::FileSecurity::Set($dir2, \%permissions);
And I get the next error:
S-1-5-11-2038111172-1292333386-11111-20315(this is not an original number and it changes this is unix FS user identifier that the AD knows how to parse)
Error handling error: 1332, LookupAccountName.
So it looks like the FileSecurity can't handle that user identifier that is coming from the unix based storage that supports both unixfs and NTFS.
This is strange because when I choose a folder for example and do "right click -> properties -> security tab" I see the numbers and then they are parsed to unixUid\user1 etc...
Any idea how to solve it?
Specifically for my case where the issue was the mixed mode on the network drive I found the next solution to be good enough for me.
I call the "icacls" system command and set permissions manually for the domain users from the folder above.
my $error = system("icacls $CreatedDir /grant domain\\user:(OI)(CI)F /T");
The code above gives full recursive permissions for the user to the folder that was created by the service with the admin user(which caused the folder to be locked only for the rood or admin user in our configuration).
Note that the command above doesn't override existing permissions but it was good enough for me.
So eventually I end up with a folder and files that are accessible to the user that called the specific service which runs with admin user.

Why am I getting "Access denied" when I have effective read permission?

I can't read a particular file, even though as far as I can tell I have read rights on it. Here is what "Effective Access" shows:
Here is what Get-Acl is giving me.
PS ...> Get-Acl .\HelloWorld.java | Format-List
Path : Microsoft.PowerShell.Core\FileSystem::I:\...\HelloWorld.java
Owner : ...\Admin
Group : G:S-1-5-21-4281937098-1570975092-1098596674-513
Access : ...\Admin Allow FullControl
Audit :
Sddl : O:S-1-5-21-3073128669-2165567304-4059943147-1001G:S-1-5-21-4281937098-1570975092-1098596674-513D:PAI(A;;FA;;;S-1-5-21-3073128669-2165567304-4059943147-1001)
When I try to open it in Notepad, or even just copy it from command-line, I get an error:
I:\...>copy HelloWorld.java C:\HelloWorld.java
Access is denied.
0 file(s) copied.
I:\...>more HelloWorld.java
Cannot access file I:\...\HelloWorld.java
I'm logged in as Admin, and also the cmd.exe shell is elevated (right clicked and did "Run as administrator").
Note that it wasn't originally SDDL_PROTECTED, but I added that (via Windows GUI) in an attempt to make sure that there wasn't something being inherited that was confusing access. Then I added an ACE to give Admin full control. The drive was formerly a system disk for a Win7 machine, but I'm trying to read it on a Win10 machine.
When the protections are OK, 2 other problems can occur
path too long: some apps don't like it (but you get file not found rather than access denied): workaround: mount a drive in a lower level using subst and access from here
file is open in write mode by another program/service.
file is encrypted using windows built-in encryption. In that case, it works OK on the original computer, but when you mount the disk somewhere else, you get "access denied" even if the permissions are OK
The chances are: it is option 3 since you switched computers.

UnauthorizedAccessException from PowerShell when using Invoke-WebRequest

I know that the error is pretty much self-explenatory but yet I am not able to find solution. I write a PowerShell script to automate the set-up project for the dev machines. There are a set of programs that must be installed so what I want to do i first download the file and then install it. I am having problems with downloading file from the web to the local machine.
My logic is as follows. I have an .xml file where I configure all the stuff. For the downloads it looks like this:
<download source="https://github.com/msysgit/msysgit/releases/download/Git-1.9.5-preview20150319/Git-1.9.5-preview20150319.exe"
destination="C:\Temp" filename="Git-1.9.5-preview20150319.exe"/>
Then in my PowerShell script file I have this function:
function install-tools() {
Set-ExecutionPolicy RemoteSigned
$xmlFileInformation = $config.SelectNodes("/setup/downloads/download");
Foreach ($file in $xmlFileInformation)
{
$("Filename: " + $file.filename)
$("File source: " + $file.source)
$("File destionation: " + $file.destination)
$("****************************************************************");
$("*** Downlading "+ $file.filename);
$("****************************************************************");
Invoke-WebRequest $file.source -OutFile $file.destination
}
$("Task finished");
}
After executin I get the error from the title UnauthorizedAccessException from PowerShell when using Invoke-WebRequest. Two things that I can mention is that I have included Set-ExecutionPolicy RemoteSigned and also, I execute the script running PowerShell as administrator. I've tried different paths but it's the same everytime, I don't get permission to write anywhere. The only thing that I can't try is using another drive I have only one - C:\.
And one strange thing - my destination directory is C:\Temp but during one of my attempts I didn't have such a directory in C:\ so I ended up with file named Temp in my C:\ but this was the closest I get to getting a file.
I don't need to save those files in a particular place since it's very possible to delete the entire directory after successfull set-up so what I need is a way to let powershell save files somewhere in my C:\ drive. Since I'm not sure if this is related with administrating my system and setting the correct rights (I tried to lower the protection as much as I can) or I miss something in my PowerShell script?
You does not specify file name to download to. Replace
-OutFile $file.destination
to
-OutFile (Join-Path $file.destination $file.filename)

Resources