Install Pm2 as a windows service [closed] - pm2

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
how to run Pm2 as a windows service .Pm2 will start the nodejs app.
I tried using pm2-windows-service
But it doesn't work.
https://www.npmjs.com/package/pm2-windows-service

use pm2-service-install to variable Pm2 to service
put the following script (ps1) into the sourcecode folder
# Deploys application as an app within a PM2 service
# Run from root of Node application
param(
[string] $Pm2Home = $env:PM2_HOME,
[string] $AppStart = "app.js"
)
$ErrorActionPreference = "Stop"
function Install-Node-Modules
{
Write-Host "Running npm install"
& "npm" i
}
function Create-Pm2-Home
{
Write-Host "Attempting to create $Pm2Home and give FullControl to LOCAL SERVICE"
New-Item -ItemType Directory -Force -Path $Pm2Home
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"LOCAL SERVICE", "FullControl", "ContainerInherit, ObjectInherit",
"None", "Allow")
try {
$acl = Get-Acl -Path $Pm2Home -ErrorAction Stop
$acl.SetAccessRule($rule)
Set-Acl -Path $Pm2Home -AclObject $acl -ErrorAction Stop
Write-Host "Successfully set FullControl permissions on $Pm2Home"
} catch {
throw "$Pm2Home : Failed to set permissions. Details : $_"
}
}
function Install-Pm2-Service
{
$UserPath = $env:userprofile
Write-Host "Installing pm2"
& "npm" i "pm2#latest" "-g"
Write-Host "Installing pm2-windows-service npm module"
& "npm" i pm2-windows-service "-g"
& "npm" install "-g" npm-check-updates
& "cd" \
& "cd" $UserPath\AppData\Roaming\npm\node_modules\pm2-windows-service
& "ncu" inquirer "-u"
& "npm" install
& "pm2-service-install" "--unattended"
# Create wrapper log file, otherwise it won't start
$wrapperLogPath = "$(npm config get prefix)\node_modules\pm2-windows-service\src\daemon\pm2.wrapper.log"
if (Test-Path $wrapperLogPath) {
Write-Debug "PM2 service wrapper log file already exists"
} else {
Out-File $wrapperLogPath -Encoding utf8
}
}
function Create-Pm2-Service-Config
{
param([string] $ConfigPath, [string] $CmdPath)
$configContent = #"
{
"apps": [{
"name": "node-app",
"script": "$($CmdPath -replace "\\","\\")",
"args": [],
"cwd": "$((Split-Path $CmdPath) -replace "\\","\\")",
"merge_logs": true,
"instances": 4,
"exec_mode": "cluster_mode",
"env": {
"NODE_ENV": "development"
}
}]
}
"#
# Write out config to JSON file
Write-Host "Writing PM2 service configuration to $ConfigPath"
$configContent | Out-File $ConfigPath -Encoding utf8
}
# From http://stackoverflow.com/a/4370900/964356
function Set-ServiceAcctCreds
{
param([string] $serviceName, [string] $newAcct, [string] $newPass)
$filter = "Name='$serviceName'"
$tries = 0
while (($service -eq $null -and $tries -le 3)) {
if ($tries -ne 0) {
sleep 2
}
$service = Get-WMIObject -namespace "root\cimv2" -class Win32_Service -Filter $filter
$tries = $tries + 1
}
if ($service -eq $null) {
throw "Could not find '$serviceName' service"
}
$service.Change($null,$null,$null,$null,$null,$null,$newAcct,$newPass)
$service.StopService()
while ($service.Started) {
sleep 2
$service = Get-WMIObject -namespace "root\cimv2" -class Win32_Service -Filter $filter
}
$service.StartService()
}
function Change-Pm2-Service-Account
{
Write-Host "Changing PM2 to run as LOCAL SERVICE"
Set-ServiceAcctCreds -serviceName "pm2.exe" -newAcct "NT AUTHORITY\LocalService" -newPass ""
}
$env:PM2_HOME = $Pm2Home
$env:PM2_SERVICE_SCRIPTS = "$Pm2Home\ecosystem.json"
[Environment]::SetEnvironmentVariable("PM2_HOME", $env:PM2_HOME, "Machine")
[Environment]::SetEnvironmentVariable("PM2_SERVICE_SCRIPTS", $env:PM2_SERVICE_SCRIPTS, "Machine")
& Install-Node-Modules
& Create-Pm2-Home
& Create-Pm2-Service-Config -ConfigPath $env:PM2_SERVICE_SCRIPTS -CmdPath $AppStart
& Install-Pm2-Service
& Change-Pm2-Service-Account
Execute the following command.
.\install.ps1 -Pm2Home "C:\Users\Admin\.pm2" -AppStart "C:\SourceCode\app.js"
In it:
C:\Users\Admin\.pm2 : .pm2 path
C:\SourceCode\app.js : App.js path
Enter the following in Promt.
? Perform environment setup (recommended)? Yes
? Set PM2_HOME? Yes
? PM2_HOME value (this path should be accessible to the service user and should not contain any “user-context” variables [e.g. %APPDATA%]): c:\etc\.pm2\
? Set PM2_SERVICE_SCRIPTS (the list of start-up scripts for pm2)? No
? Set PM2_SERVICE_PM2_DIR (the location of the global pm2 to use with the service)
? [recommended] Yes ? Specify the directory containing the pm2 version to be used by the service C:\USERS\<USER>\APPDATA\ROAMING\NPM\node_modules\pm2\index.js
Start the servive by access to Service

Related

Update value (if it exists) in JSON from Powershell

I have an appSettings.json file in the following format
{
"ConnectionStrings": {
...
},
"appSettings": {
....
"LocalVersion": "1.0.0"
},
"Logging": {
....
},
"AllowedHosts":
....
}
}
I'm trying to write a Powershell script that will update this LocalVersion property. I need to script to 1. check if appSettings object exists, 2. check if LocalVersion property is there and 2. Update the LocalVersion to a new value and save the file.
My script seems to be mostly working, however the writing to the file does not work. The value is getting changed in the Powershell script but not being saved to file.
$appSettingsPath = "C:\git\Source\src\IMStack\appsettings.json"
Write-Host "Reading JSON from " $appSettingsPath
$jsonContent = (Get-Content $appSettingsPath -Raw) | ConvertFrom-Json
Write-Host $jsonContent
if ([bool]($jsonContent.PSobject.Properties.name -match "appSettings")){
$appSettings = $jsonContent.appSettings
Write-Host "Found appSettings" $appSettings
if ([bool]($appSettings.PSobject.Properties.name -match "LocalVersion")){
$version = $appSettings.LocalVersion
Write-Host $version
$jsonContent.appSettings.LocalVersion= "1.1.1"
Write-Host "Writing " $jsonContent " with " $jsonContent.appSettings " to " $appSettingsPath
$jsonContent | ConvertTo-Json -depth 100 | Set-Content "appSettingsPath"
}
}
How can I save this JSON to the file?

What is the best way to run this loop and check while looping?

I am writing a code to check if Blue Prism process is running and if it is not to start its listener. I want to try twice and if it fails then stop. I have this
$time = Get-Date -Format "dddd MM/dd/yyyy HH:mm K"
$status = Get-Process Automate -ErrorAction SilentlyContinue
If (-not $?)
{
for ($count = 1; $count -le 2; $count++)
{
startListener
}
}
Else {
#exit
Write-Host "Up"
}
function startListener {
$time | Add-Content -Path "C:\Program Files\Blue Prism Limited\BluePrismDown.txt"
Start-Process -FilePath "C:\Program Files\Blue Prism Limited\Blue Prism Automate\Automate.exe" -ArgumentList "/resourcepc", "/public", "/port 9188", "/dbconname PROD"
Start-Sleep -Seconds 30
}
But I am not doing it correctly because there is no additional checking to see if the first try was successful.
I thought about adding another If(-not $?) but I cannot get that to work
$time = Get-Date -Format "dddd MM/dd/yyyy HH:mm K"
$status = Get-Process Automate -ErrorAction SilentlyContinue
If (-not $?)
{
for ($count = 1; $count -le 2; $count++)
{
If (-not $?)
{
startListener
}
Else
{
Break
}
}
}
Else {
#exit
Write-Host "Up"
}
function startListener {
$time | Add-Content -Path "C:\Program Files\Blue Prism Limited\BluePrismDown.txt"
Start-Process -FilePath "C:\Program Files\Blue Prism Limited\Blue Prism Automate\Automate.exe" -ArgumentList "/resourcepc", "/public", "/port 9188", "/dbconname PROD"
Start-Sleep -Seconds 30
}
I know there has got to be a better way to structure this so that I can check if it worked, if not try again and if I tried twice quit.
Augment your function to return a boolean indicating whether or not the process stops again within the 30 seconds:
function Start-BluePrismListener {
Get-Date -Format "dddd MM/dd/yyyy HH:mm K" | Add-Content -Path "C:\Program Files\Blue Prism Limited\BluePrismDown.txt"
$process = Start-Process -FilePath "C:\Program Files\Blue Prism Limited\Blue Prism Automate\Automate.exe" -ArgumentList "/resourcepc", "/public", "/port 9188", "/dbconname PROD" -PassThru
return -not $process.WaitForExit(30000)
}
The Process.WaitForExit(int milliseconds) method overload will return true if the process exits within the timeout, hence the -not. Now we can use the output of the function to decide whether to break out of the loop:
if( -not (Get-Process Automate -ErrorAction SilentlyContinue) ){
for ($count = 1; $count -le 2; $count++){
if(Start-BluePrismListener){
# didn't exit, looks good, let's break out
break
}
}
}
here's a less spiffy way to do what you asked. [grin]
swap the comment markers on lines 3 & 4 to allow testing with "failed to start" and "started properly".
# the next two allow testing for not started OR started
# comment out the one you _don't_ want to work with
$TargetProcess = 'BetterNotBeThere'
#$TargetProcess = 'notepad'
$ProcessFilePath = 'C:\windows\notepad.exe'
$RetryLimit = 2
function Get-IsProcessRunning {
[CmdletBinding ()]
Param
(
[Parameter (
Mandatory,
Position = 0
)]
[string]
$TargetProcess
)
begin {}
process
{
#($False, $True)[[bool](Get-Process -Name $TargetProcess -ErrorAction SilentlyContinue)]
}
end {}
} # end >>> function Get-IsProcessRunning
$RetryCount = 0
while (
-not (Get-IsProcessRunning -TargetProcess $TargetProcess) -and
$RetryCount -lt $RetryLimit
)
{
'Trying to start the [ {0} ] process ...' -f $TargetProcess
Start-Process -FilePath $ProcessFilePath
Start-Sleep -Seconds 5
$RetryCount ++
}
if (Get-IsProcessRunning -TargetProcess $TargetProcess)
{
'The [ {0} ] process it running at this time.' -f $TargetProcess
}
else
{
Write-Warning (' Unable to start the [ {0} ] process.' -f $TargetProcess)
}
output with the "not there" process ...
Trying to start the [ BetterNotBeThere ] process ...
Trying to start the [ BetterNotBeThere ] process ...
WARNING: Unable to start the [ BetterNotBeThere ] process.
output with notepad as the target process ...
Trying to start the [ notepad ] process ...
The [ notepad ] process it running at this time.
the 1st started two copies of Notepad.exe - i stopped them before running the 2nd. [grin]

Use a parameter switch to change how a function behaves

My main PowerShell code runs a function that logs to the Windows eventlog. If the level is error it uses a separate event ID which then our monitoring will pick up that exact ID and run an action. However, if I want to specify in the parameter of the main script (not the function) that this time running it use a different Event ID so it will NOT action monitoring, I don't know where to even start on that.
Is there a way to provide a switch parameter in the main script like $NoAlert which then changes the Event ID in the function?
The function of logging lives in a PowerShell module I created. I am importing the module at the beginning of the script and then calling the function during the main script body.
Here is the function:
function WriteLog-SRTProd {
Param(
[string]$logT,
[Parameter(Mandatory=$true)][string]$level,
[String]$LogFileDirT = "\\ServerA\Logs"
)
$RSLogfileT = (Get-ChildItem -Path $LogFileDirT |
sort LastWriteTime |
select -Last 1).Name
## make sure a level is correctly selected (mandatory)
if ("Error","Info","Warn" -NotContains $Level) {
throw "$($Environment) is not a valid name! Please use 'Error', 'Warn', or 'Info'"
}
if ($Level -eq "Info") {
Add-Content -Path "$LogFileDirT\$RSLogFileT" -Value "$(Get-Date -format MM-dd-yyyy::HH:mm:ss) INFO $logT"
Write-EventLog -LogName Application -Source TEST_MAINT -EntryType Information -EventId 100 -Message $logT -Category 0
}
if ($Level -eq "Warn") {
Add-Content -Path "$LogFileDirT\$RSLogFileT" -Value "$(Get-Date -format MM-dd-yyyy::HH:mm:ss) WARN $logT"
Write-EventLog -LogName Application -Source TEST_MAINT -EntryType Warning -EventId 200 -Message $logT -Category 0
}
if ($Level -eq "Error") {
Add-Content -Path "$LogFileDirT\$RSLogFileT" -Value "$(Get-Date -format MM-dd-yyyy::HH:mm:ss) ERROR $logT"
Write-EventLog -LogName Application -Source TEST_MAINT -EntryType Error -EventId 300 -Message $logT -Category 0
}
}
I'd like to run my script like this. When the $NoAlert is passed, it will send that switch to the function. Is this possible? Can I just add the switch in both places and use an if statement in the function for when the NoAlert switch is used?
PS C:\> .\Maintenance.ps1 -NoAlert
Param(
[switch]$NoAlert
)
WriteLog-SRTProd -level Error -logT "Custom Error Message"
I have created own function for logging and stored/installed as module, below is the part of my log module :
you can customize the write statements and add your code for event log. I have added 'NoAction' enum member as per your requirements.
I have used one Enum to separate the log levels
Enum Severity
{
Error = 3
Warning = 4
Informational = 6
Debug = 7
Verbose = 8
NoAction = 0 # AS PER YOUR REQUIREMENTS
}
function Write-Log()
{
[cmdletbinding()]
param
(
[Parameter(Position=0,mandatory=$true)]
[Severity] $LogLevel,
[Parameter(Position=1,mandatory=$true)]
[String] $Message
)
$TimeStamp = "$(Get-Date -format HH:mm:ss)" ;
Switch($LogLevel)
{
([Severity]::Error.ToString())
{
Write-Error "`t$TimeStamp : $Message`n" -ErrorAction Stop
break;
}
([Severity]::Warning.ToString())
{
Write-Warning "`t$TimeStamp : $Message`n" -WarningAction Continue
break;
}
([Severity]::Informational.ToString())
{
Write-Information "INROMATION:`t$TimeStamp : $Message`n" -InformationAction Continue
break;
}
([Severity]::Verbose.ToString())
{
Write-Verbose "`t$TimeStamp : $Message`n"
break;
}
([Severity]::NoAction.ToString())
{
Write-Verbose "`t$TimeStamp : $Message`n"
break;
}
} # END OF SWITCH
} # END OF FUNCTION
Sample Call :
Write-Log -LogLevel ([Severity]::Informational) -Message "test log message using info level"
Output :
INROMATION: 09:40:15 : test log message using info level
I have decided to just add a new parameter to both function and main script named $NoAlert. I have added an If($NoAlert){WriteLog-SRPProd -NoAlert} to the main script (messy, but its what I needed done). then in the Function, If($NoAlert){EventID 111}. so basically I am using the switch in the main script that then calls the NoAlert switch in the function. This is all done with a few added If/Else statements.
Hopefully that makes sense. Like I said its not the best answer, but I wanted to get it done and still provide an answer here in this post.

Functions & powershell remoting

I have a script that works fine but I want to improve my powershell knowledge and would like to know if there is an easier way to do this.....
Part of my script connects to a sever and pulls bak a list of files and sizes on it and exports it to a csv.
I have found a function (Exportcsv) that allows me to append to the csv with earlier versions of powershell.
At the moment I use the invoke-command to remote to each server and the run the script in the script block but this means adding the function each time. So I have the function in my script but then have to repeat it for each server I connect to so it will run remotely
Is there any way to pass the local function to the remote server so I don't have to add to each invoke command.
Invoke-Command –ComputerName server –ScriptBlock {
$wfile = "d:\folder\directorysize_H.csv"
$xfile = "d:\folder\directorysize_F.csv"
function ExportCSV {
[CmdletBinding(DefaultParameterSetName='Delimiter',
SupportsShouldProcess=$true, ConfirmImpact='Medium')]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[System.Management.Automation.PSObject]
${InputObject},
[Parameter(Mandatory=$true, Position=0)]
[Alias('PSPath')]
[System.String]
${Path},
#region -Append
[Switch]
${Append},
#endregion
[Switch]
${Force},
[Switch]
${NoClobber},
[ValidateSet('Unicode','UTF7','UTF8','ASCII','UTF32',
'BigEndianUnicode','Default','OEM')]
[System.String]
${Encoding},
[Parameter(ParameterSetName='Delimiter', Position=1)]
[ValidateNotNull()]
[System.Char]
${Delimiter},
[Parameter(ParameterSetName='UseCulture')]
[Switch]
${UseCulture},
[Alias('NTI')]
[Switch]
${NoTypeInformation})
begin
{
# This variable will tell us whether we actually need to append
# to existing file
$AppendMode = $false
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Export-Csv',
[System.Management.Automation.CommandTypes]::Cmdlet)
#String variable to become the target command line
$scriptCmdPipeline = ''
# Add new parameter handling
#region Process and remove the Append parameter if it is present
if ($Append) {
$PSBoundParameters.Remove('Append') | Out-Null
if ($Path) {
if (Test-Path $Path) {
# Need to construct new command line
$AppendMode = $true
if ($Encoding.Length -eq 0) {
# ASCII is default encoding for Export-CSV
$Encoding = 'ASCII'
}
# For Append we use ConvertTo-CSV instead of Export
$scriptCmdPipeline += 'ConvertTo-Csv -NoTypeInformation '
# Inherit other CSV convertion parameters
if ( $UseCulture ) {
$scriptCmdPipeline += ' -UseCulture '
}
if ( $Delimiter ) {
$scriptCmdPipeline += " -Delimiter '$Delimiter' "
}
# Skip the first line (the one with the property names)
$scriptCmdPipeline += ' | Foreach-Object {$start=$true}'
$scriptCmdPipeline += '{if ($start) {$start=$false} else {$_}} '
# Add file output
$scriptCmdPipeline += " | Out-File -FilePath '$Path'"
$scriptCmdPipeline += " -Encoding '$Encoding' -Append "
if ($Force) {
$scriptCmdPipeline += ' -Force'
}
if ($NoClobber) {
$scriptCmdPipeline += ' -NoClobber'
}
}
}
}
$scriptCmd = {& $wrappedCmd #PSBoundParameters }
if ( $AppendMode ) {
# redefine command line
$scriptCmd = $ExecutionContext.InvokeCommand.NewScriptBlock(
$scriptCmdPipeline
)
} else {
# execute Export-CSV as we got it because
# either -Append is missing or file does not exist
$scriptCmd = $ExecutionContext.InvokeCommand.NewScriptBlock(
[string]$scriptCmd
)
}
# standard pipeline initialization
$steppablePipeline = $scriptCmd.GetSteppablePipeline(
$myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try {
$steppablePipeline.Process($_)
} catch {
throw
}
}
end
{
try {
$steppablePipeline.End()
} catch {
throw
}
}
}
Write-Host "Removing old files from xxx"
If (Test-Path $wfile){
Remove-Item $wfile
}
If (Test-Path $xfile){
Remove-Item $xfile
}
write-host "Getting _f details"
get-childitem \\server\F$ -recurse |select directory, name, length|exportcsv $xfile -append -noclobber -notypeinformation
write-host "Getting _H details"
get-childitem \\server\H$ -recurse |select directory, name, length|exportcsv $wfile -append -noclobber -notypeinformation
}
TIA
Andy
No there isn't a straightforward way to pass the function to the remote computers, well other than what you are already doing. :-) However you can put all that script in a file (dirsize.ps1) and pass that to Invoke-Command using the FilePath parameter:
Invoke-Command –ComputerName server –FilePath .\dirsize.ps1
The file will be copied to the remote computers and executed.
try this:
#Local Function
function Get-Bits
{
Get-Service -Name BITS
}
Invoke-Command -ComputerName RemoteServer -ScriptBlock ${function:Get-Bits}
personally i put all my functions in a psm1 file in other words a module on a network share and import the module while in the remote session.

Changing NTFS security on user with fullcontrol to modify

I have thousands of folders I need to change users with Fullcontrol access to modify access. The following is a list of what I have:
A script that changes NTFS perms:
$acl = Get-Acl "G:\Folder"
$acl | Format-List
$acl.GetAccessRules($true, $true, [System.Security.Principal.NTAccount])
#second $true on following line turns on inheritance, $False turns off
$acl.SetAccessRuleProtection($True, $True)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("My-ServerTeam","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Users","Read", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl "G:\Folder" $acl
Get-Acl "G:\Folder" | Format-List
A text file with the directories and users that need to be changed from fullcontrol to modify.
I can always create a variable for the path and/or username and create a ForEach loop, but I'm not sure how to change the users that exist in the ACL for each folder to Modify, but keep the Admin accounts as full control. Any help would be appreciated.
Went another route and got what I needed. I'm not surprised noone tried to help me on this one.... it was tough. I'll post the scripts for the next person who has this issue.
There are two scripts. The first I obtained from the internet and altered a bit. The second script launches the first with the parameters required to automate.
First Script Named SetFolderPermission.ps1:
param ([string]$Path, [string]$Access, [string]$Permission = ("Modify"), [switch]$help)
function GetHelp() {
$HelpText = #"
DESCRIPTION:
NAME: SetFolderPermission.ps1
Sets FolderPermissions for User on a Folder.
Creates folder if not exist.
PARAMETERS:
-Path Folder to Create or Modify (Required)
-User User who should have access (Required)
-Permission Specify Permission for User, Default set to Modify (Optional)
-help Prints the HelpFile (Optional)
SYNTAX:
./SetFolderPermission.ps1 -Path C:\Folder\NewFolder -Access Domain\UserName -Permission FullControl
Creates the folder C:\Folder\NewFolder if it doesn't exist.
Sets Full Control for Domain\UserName
./SetFolderPermission.ps1 -Path C:\Folder\NewFolder -Access Domain\UserName
Creates the folder C:\Folder\NewFolder if it doesn't exist.
Sets Modify (Default Value) for Domain\UserName
./SetFolderPermission.ps1 -help
Displays the help topic for the script
Below Are Available Values for -Permission
"#
$HelpText
[system.enum]::getnames([System.Security.AccessControl.FileSystemRights])
}
<#
function CreateFolder ([string]$Path) {
# Check if the folder Exists
if (Test-Path $Path) {
Write-Host "Folder: $Path Already Exists" -ForeGroundColor Yellow
} else {
Write-Host "Creating $Path" -Foregroundcolor Green
New-Item -Path $Path -type directory | Out-Null
}
}
#>
function SetAcl ([string]$Path, [string]$Access, [string]$Permission) {
# Get ACL on FOlder
$GetACL = Get-Acl $Path
# Set up AccessRule
$Allinherit = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
$Allpropagation = [system.security.accesscontrol.PropagationFlags]"None"
$AccessRule = New-Object system.security.AccessControl.FileSystemAccessRule($Access, $Permission, $AllInherit, $Allpropagation, "Allow")
# Check if Access Already Exists
if ($GetACL.Access | Where {$_.IdentityReference -eq $Access}) {
Write-Host "Modifying Permissions For: $Access on directory: $Path" -ForeGroundColor Yellow
$AccessModification = New-Object system.security.AccessControl.AccessControlModification
$AccessModification.value__ = 2
$Modification = $False
$GetACL.ModifyAccessRule($AccessModification, $AccessRule, [ref]$Modification) | Out-Null
} else {
Write-Host "Adding Permission: $Permission For: $Access"
$GetACL.AddAccessRule($AccessRule)
}
Set-Acl -aclobject $GetACL -Path $Path
Write-Host "Permission: $Permission Set For: $Access on directory: $Path" -ForeGroundColor Green
}
if ($help) { GetHelp }
if ($Access -AND $Permission) {
SetAcl $Path $Access $Permission
}
The next script calls the first script and adds the needed parameters. A CSV containing 2 columns with the folders and usernames with full control.
$path = "C:\Scripts\scandata\TwoColumnCSVwithPathandUserwithFullControl.csv"
$csv = Import-csv -path $path
foreach($line in $csv){
$userN = $line.IdentityReference
$PathN = $line.Path
$dir = "$PathN"
$DomUser = "$userN"
$Perm = "Modify"
$scriptPath = "C:\Scripts\SetFolderPermission.ps1"
$argumentList1 = '-Path'
$argumentList2 = "$dir"
$argumentList3 = '-Access'
$argumentList4 = "$DomUser"
$argumentList5 = '-Permission'
$argumentList6 = "$Perm"
Invoke-Expression "$scriptPath $argumentList1 $argumentList2 $argumentList3 $argumentList4 $argumentList5 $argumentList6"