Group Policy Issue - powershell

I'm hoping you can help. For a bit of background one of our Domain Controllers is Server 2008 R2 and the other is 2012 R2, the 2012 R2 contains the more recent ADMX files. The primary DC is the 2008 version and we plan on upgrading this soon.
I have a Default Domain Policy that contains a basic logon script (.bat) that maps drives and adds documents to users desktops. This policy is Enforced and Link Enabled and pushes to all OU's.
I have an additional Policy setup within an OU that is linked to our domain, this includes a Powershell script that runs at logon. This was created on the secondary DC (2012) as it uses the "Start Screen Layout" feature within Start Menu and Taskbar - the primary DC (2008) doesn't have this features available.
For some reason the Default Domain Policy isn't running, the second policy however is successfully running. Is there any reason this might be happening? I've had a mess with the enforcement options for the second policy but I can't fathom out why it's not running both.
It's definately something to do with the Powershell commands I have running in the second policy, if I remove these the default policy login scripts run fine.
Some More Info
To explain, there's 3 scripts in total (all of which sit in the Policy location within sysvol). The first ps1 file copies a shortcut for devices and printers from a network location that all users have access to and pastes it into %appdata% for all users. Part of this script uses the startlayout.xml to reference this location which then add the shortcut to the users start menu.
Copy-Item -Path "\\Server\Share\*.lnk" -Destination "$env:APPDATA\Microsoft\Windows\Start Menu\Programs"
The next command removes a load of the bloatware that Win 10 installs to a users profile, I won't post all of the apps in the script but a few so you get the gist:
$AppList = #(
"*Microsoft.3dbuilder*"
"*AdobeSystemsIncorporated.AdobePhotoshopExpress*"
"*Microsoft.WindowsAlarms*"
"*Microsoft.Asphalt8Airborne*"
)
foreach ($App in $AppList) {
Get-AppxPackage -Name $App | Remove-AppxPackage -ErrorAction SilentlyContinue
}
The script that is added as the actual logon script references the location the two scripts above sit in and run them:
Get-ChildItem \\domain\SysVol\domain\Policies\'{Policy Number}'\User\Scripts\Logon | ForEach-Object {
& $_.FullName
}
Hope this helps, whether or not there's isn't an exit command maybe I'm not sure as I'm not too savy with Powershell scripting.
Further Update
Hi All, another update. I've made all my drive mappings and document copies through Group Policy now which eliminates the first policy therefore there is only one logon script that should run now which is to remove the Bloatware. I've decided to try and call it from a .bat file using the following command:
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File "\\domainm\SysVol\domain\Policies\{Policy Number}\User\Scripts\Logon\BloatwareRemoval.ps1"'-Wait}"
Again this will only run after a user logs on for the second time. Is there something glaringly obvious I'm missing here?Thanks in advance.
Thanks in advance.

Related

Run powershell script within powershell script (Intune related)

This is Intune related but could probably apply outside the scope of Intune as well.
I wrote a PowerShell script that downloads a folder from an Azure blob storage and extracts the content. Within the extracted folder is another PowerShell script that I want to run.
The PowerShell script is deployed in Intune and runs successfully all the way up to the point where the second PowerShell script runs. From the log, it's running into a permission issue.
Scripts deployed through Intune are ran as administrator/system and don't require any local policy change to allow the execution of PowerShell scripts on the device. However on the device, the user account is only a standard user so they don't have permissions to execute PowerShell scripts. In the first script, I've included the "Set-ExclusionPolicy Bypass" command already.
I need to be able to deploy the script from Intune to the local device and essential run another script as the local user (non administrator account). I thought maybe I needed the local user to be included in the local administrators group to be able to run the second script but that did not work either.
Also read somewhere that PowerShell can run PowerShell scripts from other PowerShell scripts directly. The only time you need Start-Process for that is when you want to run the called script with elevated privileges (which isn't necessary here, since your parent script is already running elevated).
^^^Is this my issue? My script does include "Start-Process" to run the next powershell script.
Script below for reference.
New-Item -Path "C:\IT Drivers" -ItemType Directory ;
Invoke-WebRequest - Uri 'https://xyz.zip' -OutFile "C:\xyz.zip" ;
Expand-Archive -Path "C:\xyz.zip" -DestinationPath "C:\";
Set-ExclusionPolicy Bypass ;
Start-Sleep -Seconds 30 ;
Start-Process powershell "C:\xyz.ps1"
Any guidance would be appreciated, thank you!

Powershell - How to use Start-Process to call file from share/pass args in single line

To preface this, I am self teaching and brand new to scripting in general, let alone powershell.
After a cumulative 12 hours, my Google fu has run out.
I had a series of programs tailored to different models of computer we support that ran a staged series of installers from a fileshare. The program would check to see if the tech deploying the software was running it as admin, if not, it used a Start-Process line to elevate and run again.
It worked flawlessly, but we wanted to see if we could remove the need for the tech to enter r to run the scripts from the share.
In trying to figure out how to add -executionpolicy bypass to the arg list for Start-Process, I've hit a wall.
It now errors on trying to call to the fileshare to retrieve the parent script, before getting to the point where I can troubleshoot the bypass can of worms.
Below is my rough framework, remember I'm self taught by googling and using tutorials point.
$principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if($principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
#usually I have a get-childitem | foreach-object loop here that runs the files from the folder one by one in a specific order,
#it also checks to see if msiexec is running or not before trying to load and install files using a if-else>do-while combo
}
else
{
Start-Process -FilePath "powershell" -ArgumentList "$('-File "\\server\dir\foo".ps1')$($MyInvocation.MyCommand.Name)$('""')" -Verb runAs
}#this calls to a script that is a 1:1 copy of the code in the if{} block
This returns an error from the -File parameter that says it can't call the file because it doesn't exist.
What am I doing wrong?
How do I pass -executionpolicy bypass as an additional arg without breaking it further?
Is there a better way to do this?
Is there a neater way to automate this?
Please help me geniuses of StackOverflow before I start gnawing on my keyboard.

Allow Win 10 user to reset network adaptor via PS script without UAC

Firstly: I have found a number of questions answered that do everything but allow me to bypass UAC. I am IT for a small business, but it is not my primary responsibility.
I have two machines in my domain that on startup often fail to correctly connect to the domain network. Restarting the network adapter fixes the issue until the machine restarts. Unfortunately, one of the machines is used by a non-admin, and a technically illiterate one at that.
I hoped to use a powershell script to do this. Using this website, I created script and batch files to solve the issue. Since the computer only has one network adaptor, I went simple:
internet.ps1
Get-NetAdapter | Restart-NetAdapter
internet.cmd
#ECHO OFF
SET ThisScriptsDirectory=%~dp0
SET PowerShellScriptPath=%ThisScriptsDirectory%internet.ps1
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%PowerShellScriptPath%""' -Verb RunAs}";
Unfortunately, I don't fully understand the last command in the batch file. As such I struggle to research the command to pass some form of user credential. This environment is not very secure. But I don't want to give this user domain admin permissions generally, or provide them with some admin credentials which would end up on a sticky note. Either option is just inviting trouble from my older, technically illiterate colleagues. And going over to punch in credentials every day is time consuming.
I am looking for a script that cycles the network adaptor and provides the necessary credentials to make that change so a non-admin user can fix their domain and internet access without having admin credentials on a post-it note.
You could schedule a task using the Task Scheduler in Windows. When scheduling a task, you can specify credentials for the task to use when it runs. You can add a trigger for this task to have it run when the computer starts, or you can simply allow the user to manually start it.
If you decide to go this route, there is a check box you can check that runs the program with the highest possible privileges. The entire point of that last line is to start a new PowerShell window that runs as administrator so it actually has permission to restart the adapter. This means that you can get rid of almost your entire script, and just keep the part that actually restarts the adapter.
For example, when you go to create a new task in Task Scheduler, under the Actions tab, you can create a new action and enter the following:
Program/script:
PowerShell
Add arguments:
-Command "Get-NetAdapter | Restart-NetAdapter"
Note: I'm not sure if this is still the case, but in my past experience, sometimes it will try to run before Windows is fully loaded. If it doesn't seem to be doing anything on startup, you may need to add a delay to it. You can do this by running the Start-Sleep command. You can add it to the arguments field by doing the following:
-Command "Start-Sleep 5; Get-NetAdapter | Restart-NetAdapter"
Replace the number 5 with how many seconds you would like it to wait.

Copy file from a Network Drive to a local Drive with a Jenkins Agent

So here is the situation, I am trying to automate the copy of some files that are in a network drive into a local folder on one of my servers. The task seems to be simple and when I try the code with PowerShell or with x copy in the command line both are working pretty great.
I've installed a Jenkins agent on this Windows server 2016 server and run the agent as a service. When I try to run the same code from the Jenkins agent, it is never working.
I tried starting the agent service as local system and as the windows network administrator who has all the right
I tried with PowerShell those lines :
Copy-Item -Path "\\server IP\directory\*" -Destination "D:\Directory\" -Verbose
and
Copy-Item -Path "z:\*" -Destination "D:\Directory\" -Verbose
Both return no error but did not copy the files, and when I tried the same code with x copy I just receive no file found and the file was not copied
xcopy "\\server IP\directory\*" "D:\Directory\" /f /s /h /y
xcopy "z:\*" "D:\Directory\" /f /s /h /y
With PowerShell, I also tried inserting the copy-file command into a script and only calling the script with the Jenkins agent, and it also didn't work
I am now running in a circle and wonder how are we supposed to work with the network drive with the Jenkins agent? Or what I am doing wrong ?
Note that other PowerShell code are working great locally.
I tried starting the agent service as local system and as the windows network administrator who has all the right
Local system doesn't have any network permissions by default. This is the machine account, so you would have to give the machine access to "\\server\share". It is not advisable though, because permissions should be granted on finer granularity. Also, local system has too many local rights, which Jenkins doesn't need.
I don't know what you mean by "Windows Network Administrator". It sounds like this one would also have too many rights.
Usually, one creates a dedicated Jenkins (domain) user. This user will be granted access to any network paths it needs. Then you have two options:
Always run Jenkins service as this user (easiest way).
Run Jenkins under another local user and connect to network drives as the domain user only on demand: net use \\server\share /user:YourDomain\Jenkins <Password>. This adds some security as you don't need to give any local permissions to the domain user.
Both return no error but did not copy the files
To improve error reporting, I suggest you set $ErrorActionPreference = 'Stop' at the beginning of your PowerShell scripts. This way the script will stop execution and show an error as soon as the first error happens. I usually wrap my PS scripts in a try/catch block to also show a script stack trace, which makes it much easier to pinpoint error locations:
$ErrorActionPreference = 'Stop' # Make the script stop at the 1st error
try {
Copy-Item -Path "\\server IP\directory\*" -Destination "D:\Directory\" -Verbose
# Possibly more commands...
# Indicate success to Jenkins
exit 0
}
catch {
Write-Host "SCRIPT ERROR: $($_.Exception)"
if( $_.ScriptStackTrace ) {
Write-Host ( "`t$($_.ScriptStackTrace)" -replace '\r?\n', "`n`t" )
}
# Indicate failure to Jenkins
exit 1
}
In this case the stack trace is not much helpful, but it will come in handy, when you call functions of other scripts, which in turn may call other scripts too.

Deleting all locally stored user profiles on log off

I want to delete all locally stored user profiles on logoff using a Powershell script. I've the following script:
Set-ExecutionPolicyRemoteSigned[gc]::collect()
cmd /c start reg unload "HKCU"Remove-PSDrive HKCU import-module C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ManageUserProfiles\ManageUserProfiles.PSM1
get-userprofile |where{ $_.SID -ne ("S-1-5-21-3071724114-2656578308-4228372245-500")} | remove-userprofile
I'm a complete newbie to powershell. So could someone tell me whether this script meets my needs and how does it run? And could you also explain what $_.SID -ne ("S-1-5-21-3071724114-2656578308-4228372245-500") means too. Thanks in advance.
I am not familiar with the module that you are running, and it looks like that should be 6 lines not 3 (insert break before [gc], before Remove-PSDrive, and before Import-Module).
Next, add a space between Set-ExecutionPolicy and RemoteSigned.
Now, the script appears to collect user profiles, pipes them through a Where statement that excludes the Administrator account from the list of profiles, and then removes all remaining profiles. Let's step through it...
Set-ExecutionPolicy RemoteSigned
This sets your execution policy. I'm going to assume this is to avoid issues with an unsigned module that you load in a couple steps.
[gc]::collect()
This forces the garbage collection to clean up memory and remove unused resources. This line can probably be skipped.
cmd /c start reg unload "HKCU"
This uses the reg.exe command line application to unload the HKEY_CURRENT_USER hive from within the current registry set. This would need to be done before deleting a profile since you can't delete files that are in use.
Remove-PSDrive HKCU
This does pretty much the same thing, but for PowerShell's registry provider. I'm guessing this is so that you don't get errors, or so that it doesn't try to reload the HKCU hive.
C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ManageUserProfiles\ManageUserProfiles.PSM1
This loads the 'Manage User Profiles' module. I am not familiar with the module, but you would need to make sure that you have that module installed on the computer that this is running on, so if you are running this on all of your computers you need to install that module on all of your computers.
get-userprofile |where{ $_.SID -ne ("S-1-5-21-3071724114-2656578308-4228372245-500")} | remove-userprofile
This is a command from the module you just loaded. It will, I assume, get user profiles as some sort of custom object, and then it pipes to a Where statement that excludes the Administrator account by stating that it only allows profile objects that do not (-ne is the 'not equal' operator) have a SID property equal to "S-1-5-21-3071724114-2656578308-4228372245-500". So all user profiles except the admin account's profile are then piped to the Remove-UserProfile command, which we can probably assume deletes each profile that is piped to it.
Hopefully that explains what your script is doing.