Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

this script icacle doesn't work on remote computers. please help

Posted on 2016-11-22
11
Medium Priority
?
121 Views
Last Modified: 2016-11-30
I had this question after viewing Powershell script- running set owner command on multiple servers at once.

Hello,
I have closed the question because the error was fixed and I can run the script now, but the icacle command still only works on the local computer and if I execute it through the command NOT powershell.

I get this error

OI : The term 'OI' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At line:1 char:45
+ icacls F:\ /grant TESTTARGET\user.svc:(OI)(CI)F
+                                             ~~
    + CategoryInfo          : ObjectNotFound: (OI:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException



Here is the script.
Please help:


Function Set-Permissions {
[CmdletBinding()]
    param([Parameter(Mandatory=$true,
    ValueFromPipeline=$true,
    ValueFromPipelineByPropertyName=$true)]
    [Alias('hostname')]
    [string[]$ComputerName,
    [switch]$nameLog
)
Begin {

 if ($nameLog)
   {
       Write-Verbose "Finding name log file"
       $i = 0
    do {
    $logFile = "names-$i.txt"
    $i++
    } while (Test-Path $logFile)
    Write-verbose "Log file name will be stored $logfile"

    }
else {
write-verbose "Name logging off"
   }

}
Process {
if ($nameLog)
    {
        Write-Verbose
         "Name log on"
    }
    else
    {
       Write-Verbose "Name log off"
    }

    foreach ($computer in $computername) {
    Write-Verbose "Now connecting to $computer"
    if ($nameLog){
    $computer | out-file $logFile -Append
    }


 icacls E:\ /grant TESTTARGET\user.svc:(OI)(CI)F
    icacls E:\ /grant TESTTARGET\test.mig.svc:(OI)(CI)F
    icacls F:\ /grant TESTTARGET\user.svc:(OI)(CI)F
    icacls F:\ /grant TESTTARGET\test.mig.svc:(OI)(CI)F
    icacls E:\ /grant TESTTARGET\test.Administrators:(OI)(CI)F
    icacls F:\ /grant TESTTARGET\test.Administrators:(OI)(CI)F
    icacls "E:\Includes" /setowner TESTTARGET\user.svc /t /c
    icacls "E:\test" /setowner TESTTARGET\user.svc /t /c
    icacls "E:\Program Files" /setowner TESTTARGET\user.svc /t /c
    icacls "F:\Software" /setowner TESTTARGET\user.svc /t /c
 
}

}

End {}


}




Set-Permissions -computername server01, server02
0
Comment
Question by:creative555
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 3
11 Comments
 
LVL 41

Expert Comment

by:footech
ID: 41898396
Often when calling externals applications, it is a matter of trying quoting different parts, or even escaping certain characters.  
This should work.
icacls E:\ /grant "TESTTARGET\user.svc:(OI)(CI)(F)"
#or
 icacls E:\ /grant TESTTARGET\user.svc:`(OI)`(CI)`(F)

Open in new window


Another useful technique if using PS 3.0+ is "--%" (the stop parsing operator).
icacls E:\ --% /grant TESTTARGET\user.svc:(OI)(CI)(F)

Open in new window

0
 

Author Comment

by:creative555
ID: 41902719
Hello,
thank you so much

With quotes the script is now working but still not updating the remote computer. It doesn't give me any error either.
icacls E:\ /grant "TESTTARGET\user.svc:(OI)(CI)(F)"

Is this the correct command?
Invoke-Command -ComputerName (Get-Content ".\servers.txt") | Set-Permissions

I ran this command with the script and it only updated the local computer
Set-Permissions -computername server01, server02.testtarget.local
0
 

Author Comment

by:creative555
ID: 41902739
oh. I made this work without using a function. How do I pass the function in the script block?

Invoke-Command -ComputerName server02.testtarget.local -Scriptblock {icacls E:\ /grant "TESTTARGET\Administrators:(OI)(CI)F"} -cred testtarget\service

This didn't work with the script I posted above
Invoke-Command -ComputerName server02.testtarget.local -Scriptblock {get-permissions} -cred testtarget\service
0
Vim Reference Guide

Vim is a powerful text editor favored by many sysadmins and developers - here are some commands that you'll want to keep in your back pocket!

 
LVL 41

Expert Comment

by:footech
ID: 41903467
Just like variables have scope, functions don't exist outside of the session in which they were defined/created.  Say you open a PS console and create the function, then open another PS console and try to run the function in that window/session - it won't work because the function was only created in the first session.  The same thing applies to remote sessions.

So the only way to run a function in a remote session is to define the function in that remote session.  Just like in a local session, you first run the code that defines the function, then you run the function.  Using the Invoke-Command cmdlet, your scriptblock that you call to be run has to include all those elements.
0
 

Author Comment

by:creative555
ID: 41904809
ok. I understand what you are saying but how to make it work.

Ok, I revised the script but somehow it still doesnt process the remote computer. Posting the revised script here .

Please help. See the screenshot with the results.

Set-Location "c:\cfscripts"

Function Set-Permissions {
[CmdletBinding()]
    param([Parameter(Mandatory=$true,
    ValueFromPipeline=$true,
    ValueFromPipelineByPropertyName=$true)]
    [Alias('hostname')]
    [string[]]$ComputerName,
    [switch]$nameLog
)
Begin {

 if ($nameLog)
   {
       Write-Verbose "Finding name log file"
       $i = 0
    do {
    $logFile = "names-$i.txt"
    $i++
    } while (Test-Path $logFile)
    Write-verbose "Log file name will be stored $logfile"

    }
else {
write-verbose "Name logging off"
   } 

}
Process {
if ($nameLog)
    {
        Write-Verbose "Name log on"
    }
    else
    {
       Write-Verbose "Name log off" 
    }

try {
   $cred = get-credential
   foreach ($computer in $computername) {
    if ($nameLog){
    $computer | out-file $logFile -Append
    } 
    Write-Verbose "Now processing $computer"
    Enter-PSSession -computername $computer -Credential $cred 
    write-host "Connected to $computer" -ForegroundColor Green
    whoami;hostname
    icacls E:\ /grant "TESTTARGET\Administrators:(OI)(CI)F"
    icacls F:\ /grant "TESTTARGET\Administrators:(OI)(CI)F"
    
    Exit-PSSession
    }
}
catch
{}

}#Process
#End {}


}


$computers = (Get-content ".\servers.txt")
Set-Permissions -computername $computers -nameLog -verbose

Open in new window

0
 

Author Comment

by:creative555
ID: 41904816
It doesn't enters into remote session
0
 

Author Comment

by:creative555
ID: 41904852
I added these lines but getting this error.
Please help

$s = New-PSSession -computername $computers -Credential $cred
invoke-command -Session $s -ScriptBlock ${function:Set-Permission

Invoke-Command : Cannot validate argument on parameter 'ScriptBlock'. The argument is null. Provide a valid value for the argument, and
then try running the command again.
At C:\cfscripts\Set-FilePermissions2.ps1:73 char:41
+ invoke-command -Session $s -ScriptBlock ${function:Set-Permission}

here is modified script that is still failing


Set-Location "c:\cfscripts"
 $cred = get-credential
 $computers = (Get-content ".\servers.txt")
 $s = New-PSSession -computername $computers -Credential $cred


Function Set-Permissions {
[CmdletBinding()]
    param([Parameter(Mandatory=$true,
    ValueFromPipeline=$true,
    ValueFromPipelineByPropertyName=$true)]
    [Alias('hostname')]
    [string[]]$ComputerName,
    [switch]$nameLog
)
Begin {

 if ($nameLog)
   {
       Write-Verbose "Finding name log file"
       $i = 0
    do {
    $logFile = "names-$i.txt"
    $i++
    } while (Test-Path $logFile)
    Write-verbose "Log file name will be stored $logfile"

    }
else {
write-verbose "Name logging off"
   } 

}
Process {
if ($nameLog)
    {
        Write-Verbose "Name log on"
    }
    else
    {
       Write-Verbose "Name log off" 
    }

try {
  
    
   foreach ($computer in $computername) {
    if ($nameLog){
    $computer | out-file $logFile -Append
    } 
    Write-Verbose "Now processing $computer"
    
    write-host "Connected to $computer" -ForegroundColor Green
    whoami;hostname
    icacls E:\ /grant "TESTTARGET\ADMS.Administrators:(OI)(CI)F"
    icacls F:\ /grant "TESTTARGET\ADMS.Administrators:(OI)(CI)F"
    
    
    }
}
catch
{}

}#Process
#End {}


}


#$computers = (Get-content ".\servers.txt")
#Set-Permissions -computername $computers -nameLog -verbose
invoke-command -Session $s -ScriptBlock ${function:Set-Permission}

Open in new window

0
 
LVL 41

Accepted Solution

by:
footech earned 2000 total points
ID: 41904873
Try the below.  I didn't show putting the function in the scriptblock because I would have to rewrite most of the function to work correctly, including moving the looping through computers outside of the function, changing the logging (you have to keep in mind whether your code would be writing to a file on the remote computer or on your local machine)
Function Set-Permissions {
[CmdletBinding()]
    param([Parameter(Mandatory=$true,
    ValueFromPipeline=$true,
    ValueFromPipelineByPropertyName=$true)]
    [Alias('hostname')]
    [string[]]$ComputerName,
    [switch]$nameLog
)
Begin {

    if ($nameLog)
    {
       Write-Verbose "Finding name log file"
       $i = 0
        do {
            $logFile = "names-$i.txt"
            $i++
        } while (Test-Path $logFile)
        Write-verbose "Log file name will be stored $logfile"

    }
else {
    write-verbose "Name logging off"
} 

}
Process {
if ($nameLog)
    {
        Write-Verbose "Name log on"
    }
    else
    {
       Write-Verbose "Name log off" 
    }

try {
    $cred = get-credential
    foreach ($computer in $ComputerName) {
        if ($nameLog){
            $computer | out-file $logFile -Append
        } 
        Write-Verbose "Now processing $computer"
        Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock {
            Write-Host "Connected to $($env:computer)" -ForegroundColor Green
            whoami;hostname
            icacls E:\ /grant "TESTTARGET\Administrators:(OI)(CI)F"
            icacls F:\ /grant "TESTTARGET\Administrators:(OI)(CI)F"
            }
    }
}
catch
{}

}#Process
#End {}

}



Set-Location "c:\cfscripts"
$cred = Get-Credential
$computers = (Get-content ".\servers.txt")
Set-Permissions -computername $computers -nameLog -verbose

Open in new window


Here's a truncated example of defining the function (and calling it) in the scriptblock which will be run on the remote machines.
$scriptblock = {
    Function Set-Permissions {
    [CmdletBinding()]
    param(
        [switch]$nameLog
    )
    # do stuff here
        icacls E:\ /grant "TESTTARGET\Administrators:(OI)(CI)F"
        icacls F:\ /grant "TESTTARGET\Administrators:(OI)(CI)F"
    } # End function definition

    # Now run the function
    Set-Permissions -nameLog -verbose
}

Set-Location "c:\cfscripts"
$cred = Get-Credential
$computers = (Get-content ".\servers.txt")
Invoke-Command -ComputerName $computers -Credential $cred -ScriptBlock $scriptblock

Open in new window

0
 

Author Comment

by:creative555
ID: 41908055
I got this error on the trunkated example:

Successfully processed 0 files; Failed processing 1 files
TESTTARGET\Administrators: No mapping between account names and security IDs was done.
    + CategoryInfo          : NotSpecified: (TESTTARGET\Admi...y IDs was done.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
    + PSComputerName        : Server02.testtarget.local
 
TESTTARGET\Administrators: No mapping between account names and security IDs was done.
    + CategoryInfo          : NotSpecified: (TESTTARGET\Admi...y IDs was done.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
    + PSComputerName        : Server02.testtarget.local
 
Successfully processed 0 files; Failed processing 1 files
Successfully processed 0 files; Failed processing 1 files
0
 

Author Comment

by:creative555
ID: 41908056
oh my fault. It is working now!! You are brilliant. I had a group wrong here because I didn't post the real group name.

 icacls E:\ /grant "TESTTARGET\Administrators:(OI)(CI)F"
        icacls F:\ /grant "TESTTARGET\ADMS.Administrators:(OI)(CI)F"
0
 

Author Closing Comment

by:creative555
ID: 41908058
thank you so much! Tested and it is working great now!
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Recently we ran in to an issue while running some SQL jobs where we were trying to process the cubes.  We got an error saying failure stating 'NT SERVICE\SQLSERVERAGENT does not have access to Analysis Services. So this is a way to automate that wit…
In this post we will be converting StringData saved within a text file into a hash table. This can be further used in a PowerShell script for replacing settings that are dynamic in nature from environment to environment.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

664 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question