Powershell Folder Inheritence problem - powershell

I am having problems with a powershell script i basically trying to reset the permission on a folder, by removing the following groups
NT AUTHORITY\Authenticated Users
BUILTIN\Users
If i manually change the folder to not inherit from it parent the script works, I have look through google to find best way of removing the inheritance via a script the script compiles but not do anything.
This is the command i am using
$WebsiteACL =Get-Acl -Path "C:\websites"
$WebsiteACL.SetAccessRuleProtection($true,$false)
Does anyone have any sugestion?

Personally I find Get-Acl and Set-Acl still too much of a PITA to use (and I'm a C# dev). You can use icacls.exe to accomplish your task easily:
icacls C:\temp\foo /inheritance:d
It also supports removing groups. Check out its usage: icacls /?.

Get-Acl/Set-Acl can be a royal pain unless you're the owner of the object you're trying to change permissions on -- even if you're an Administrator. If you want to change an ACL on an object you don't own you have to have the SeBackupPrivilege enabled for your identity/account. The only easy way I know of to modify system privileges is install PowerShell Community Extensions and use Get/Set-Privilege. I really don't understand why this limitation exists but it does.
With that said, using icacls works very well under most conditions. There is a bug if you're setting permissions on a directory accessed through a share with Access Based Enumeration enabled. Everyone does this right? ;)
Touching a directory underneath an ABE controlled share with icacls causes the directory to disappear even if you still have permissions to that directory. If you use the Windows Explorer ACL editor to read and (re)apply the permissions set with icacls the directory is visible again.
After much head scratching it was determined that icacls was doing something to the synchronize bit. Without synchronize ABE causes the directory to be invisible. The simplest workaround would be to not use ABE but in our environment disabling ABE is not an option.
Another solution is use SetACL.exe which you can download from SourceForge. It has a very complicated syntax, imho, but is really powerful. It's also available as a OCX so you can script it via PowerShell.

Related

Write to Profile File After Installing PowerShell Module with PowerShellGet

I have a custom PowerShell module with two cmdlets. I have it successfully, but manually, deployed on my machine. However, I deployed it by placing the binary file and module manifest in a location, and then registering the module. I also had to manually write an Import-Module command into my 'all users' profile.
Now I am sure I can deploy this module with Publish-Module, but how do I get the Install-Module to write the Import-Module statement to the profile file?
As of PowerShell 3.0, a module is automatically imported when a command from the module is invoked. This was a brilliant on Microsoft's part; however, it did require that modules are located in a location where PowerShell looks for modules by default. Makes sense. You can see those locations by running the following command:
$env:PSModulePath -split ';'
Is there a reason you'd rather not use one of the paths stored in the above environmental variable? That said, I'd keep your code out of the "C:\Windows\System32..." path. The other options are better: "C:\Program Files\PowerShell\Modules" (AllUsers) and "C:\Users\tommymaynard\Documents\PowerShell\Modules" (CurrentUser). Depending on your PowerShell version/OS, those path could be different. You won't need to write an Import-Module command into a $PROFILE script if you get the module into a preferred location. Maybe you already know this, but maybe not.
You're not going to get Install-Module to write to any of the $PROFILE scripts.
$PROFILE | Select-Object -Property *
Well, not by default anyway. You could write your own Install-Module function, that runs PowerShellGet's Install-Module function, and includes writing to various $PROFILE scripts. The problem is that you'll need to include logic so you don't blow away the contents of someone's $PROFILE script if it's not empty, and only append to it.
Seriously though, this is turning into a lot of work, when you could drop the module into a location where PowerShell can find it on its own.
Edit: It just occurred to me, you can add a value/path to the $env:PSModulePath environmental variable. It's a single string with semi-colon delimiters:
$env:PSModulePath.GetType().Name
Therefore, it'd look like this:
$env:PSModulePath += ';C:\Another\Path'
That's great and all, but again how might you stage this, right? It takes you back to the write-to-all-the-$PROFILE-scripts problem,... although you may be able to update the variable via Group Policy Preferences. Again, probably better to just relocate your module.

Running powershell script with CMake through Visual Studio without changing system-wide permissions

I want to zip up a folder. This is easy on operating systems like Linux where it's easy for the system admin to install the command line zip tool like apt install zip. Unfortunately on Windows it's not that straight forward.
A simple workaround I've found is that I can use Compress-Archive in a powershell script like this:
Compress-Archive -Path $folder -CompressionLevel Optimal -DestinationPath $zipPath
and then invoke this with the folder and zipPath before or after project building.
To do this, my CMakeLists.txt will have a line like:
execute_process(COMMAND powershell ${powershellScriptPath} "\"${folderPathToZip}\"" "\"${outputZipPath}\"" OUTPUT_QUIET)
This works fine, except I have to allow scripts to run globally and unsafely on my computer.
I want this to just work on any Windows computer without having to require the people to do any tinkering of settings. I also don't like the idea of getting other developers to allow scripts globally and unsafely for obvious reasons. I'd like my developers to be able to open the project and press build and it all works, and this is the last thing standing in my way from making it happen.
Is there a way to be able to get this script to run by changing the way the program is invoked? Or am I stuck and have to find another way to do this? Or is there some way to whitelist this specific file automatically without the user having to do any extra steps?
The only other hacky way around this would be for me to write my own zip utility that is invoked on every build to zip up the stuff, but that is a bunch of work for something that feels so close to being operational.
Edit: I can safely make the assumption that the computer has powershell installed and is relatively modern
You can bypass the effective PowerShell execution policy by passing -ExecutionPolicy Bypass to the PowerShell CLI (powershell.exe in the case of Windows PowerShell):
execute_process(COMMAND powershell -ExecutionPolicy Bypass -File ${powershellScriptPath} ${folderPathToZip} ${outputZipPath} OUTPUT_QUIET)
Also note that I'm using -File so as to instruct Windows PowerShell to execute a script file, because it defaults to -Command[1], which changes the interpretation of the arguments[2]; I'm not familiar with cmake, but the hope is that it provides double-quoting around the arguments by default / as necessary, which with -File should be sufficient.
[1] Note that PowerShell Core defaults to -File.
[2] For details, see the 2nd and subsequent sections of this answer.

How to run a powershell script at active directory login

I created a group policy in In Group Policy Management Editor, in the navigation pane, expand User Configuration, expand Policies, expand Windows Settings, and then click Scripts (Logon/Logoff). I made a logon script as a ps1 file:
copy-item "\\server1\Pictures\background.jpg" -Destination "C:\screensaver\" -Recurse
I added that ps1 file in the powershell scripts part of the group policy and set it to run powershell scripts first.
I didn't use any parameters which may be causing the issue?
I need each computer to have that c:\screensaver\background.jpg image when they login.
It's the only group policy applied to that OU, all the PCs are Windows 10, and the domain controllers are Windows 2012 r2.
In my opinion creating a (PowerShell-) logon-script for copying a file is not a great solution and out-of-date nowadays.
Make your life easier and use group-policy-preferences for this task. You don't have to create scripts for that.
Open the Group Policy Management Console, select your policy, open the "Preferences"-Node and select "Files". Create a new element and select the source- and the target (as shown below).
After that reboot the client and the file should get copied without coding.
Sounds like there's two parts to implementing your request. Before doing any of the following, make sure that you can log in as one of the users, and manually perform the steps you want the script to complete (to make sure any user restrictions aren't holding you up). So, make sure you can navigate to the remove image location \\server1\Pictures\background.jpg, and copy it to the local folder C:\screensaver.
Copying the file to the target machine. You provided the contents of your PS1 file as copy-item "\server1\Pictures\background.jpg" -Destination "C:\screensaver\" -Recurse. I believe you'll want to have two slashes "\\" at the beginning of your \server1 string, resulting in "\\server1\Pictures\background.jpg" (the two slashes make this a valid UNC path). Additionally, you included the -Recurse parameter. I don't understand the need for this parameter, based off of the documentation, accessible via the command Get-Help Copy-Item -Full.
-Recurse [<SwitchParameters>]
Indicates that this cmdlet performs a recursive copy.
I would suggest that you include the -Force parameter. If you ever update that image, the next time a user logs on, they'll receive the updated image. Without the -Force parameter, the command might not overwrite the existing image on disk. Also, you shouldn't need the trailing slash on the -Destination parameter. I would suggest the command resemble:
Copy-Item "\\server1\Pictures\background.jpg" -Destination "C:\screensaver\" -Force
Configuring the wallpaper via Group Policy The first link I found via Google Search set windows 10 wallpaper via group policy with anything that looked like useful steps was some grouppolicy.biz website. I haven't been able to test them, but the main point being that you'll need to make sure that you're actually telling the computer to use the wallpaper you've copied into place.
If you make sure that you've addressed the above items, then it should work for you. There may be some considerations for the first time a user logs in, if the image isn't copied over, then the wallpaper may not display until the second time they log in.

Missing Help Files in Powershell V5.0

Powershell Version: 5.0.10586.494
I just began working with powershell this weekend and I discovered that I cannot find any help files when using the shell, for example, I was looking to read the about_Comparison_Operators help file but it seems as though the console cannot find it.
When doing: Get-Help About_* the only result I get is About_CimSession... it seems like there are no other help files?
This TechNet article suggests that in Powershell v3 the module must be imported,
To download or update the help files for a module in Windows PowerShell 3.0, use the Update-Help cmdlet.
I don't know if it's the same deal in my case? I've used the update-help cmdlet (as admin) and it does not seem to effect the help files.
Thanks!
EDIT: Forgot to mention, I've been running PS as admin while trying to update help. This runs without error, but the help files remain untouched.
UPDATE: Still no luck, tried updating help by specifying language using the UICulture parameter but this didn't make a difference. Will keep this post updated if I find a fix.
Update: PowerShell updatable help is no longer broken. About_ helpfiles are now downloaded with the correct extension. The formatting of these plaintext files still doesn't equal the old versions, however.
PowerShell updatable help is currently broken. PS5 doesn't ship with those about_* helpfiles, and if you update-help to download them, they aren't stored with the appropriate file extension, so get-help doesn't read them.
Only recently were these files being downloaded at all, so if you haven't tried in a while you should still do update-help -force in an elevated session. Then, see this answer for a one-liner that will rename the files correctly: https://superuser.com/a/1134681/4782
However, due to a (probably) unrelated issue, these new help files have some mangled text formatting that makes them very difficult to read any time a table-like layout is being used. If you'd like instead to grab the PS4-era about_* files with proper formatting and use those instead, an alternative solution can be found here: https://github.com/kilasuit/Install-AboutHelp. Note that this solution will unzip an archive of about_* files to the en\ locale folder, which may not be your default locale (mine is en-US\, for example). This will work fine since the en\ location will be used as a fallback as long as the desired document doesn't exist in your default locale's folder.
Further reference:
https://github.com/PowerShell/PowerShell/issues/2028
https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/15832144-powershell-5-on-windows-10-server-2012-helpfiles-a
https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/17014843-core-help-files-as-of-2016-11-08-have-broken-tex
FOR non-English OS only
If you are using PowerShell v5 on an operating system that has not the "en-US" language settings then update-help tries to download the help files for your language which might not be available. Use:
Update-Help -UICulture "en-US"
in an elevated (admin) console.
Background
You can check your language setting with the cmdlet get-culture. In my case I get:
PS C:\> Get-Culture
LCID Name DisplayName
---- ---- -----------
1031 de-DE Deutsch (Deutschland)
and at least today (20.7.2017) there are help-files missing (for example get-services). Note that the get-help applet will still first look for help files in your language before it will resort to "en-US" Quelle (in Deutsch).

Powershell: Get the default directory from inside a cmdlet

I'm writing a powershell cmdlet. From inside of my cmdlet BeginProcessing() method, I want to be able to retrieve the the directory that was the default directory at the time the cmdlet was invoked.
Example:
If the user does this:
cd \myDirectory
invoke-mycmdlet
I want for my code to know that the default shell directory was c:\myDirectory.
When I access Environment.CurrentDirectory, it's always c:\windows\system32
I've seen a similar post on SO where the poster needed to set Environment::Current directory from inside the shell using get-location. That won't work for me.
Basically, my cmdlet does some file system stuff, and I want the user to be able to just cd\ into a directory, and execute my cmdlet, with it operating on the directory that they switched into -- just like you would expect it to work from the old Command Console.
You might want to try this instead, CurrentLocation.Path could also point to other provider paths, such as the registery.
this.SessionState.Path.CurrentFileSystemLocation.Path
You know, I always seem to find it right after I post -- regardless of how long I spent looking before reaching for SO!
So, my cmdlet inherits from PsCmdlet. I found that I could get the path I wanted from
this.SessionState.Path.CurrentLocation.Path
(where "this" is a cmdlet class that inherits from PsCmdlet)
Try the Get-Location cmdlet. It should be the script's current executing location, rather than the powershell host startup folder.