0

I have a particular use case that requires a lot of my powershell scripts to change the user context they run under. I have code that works reliably, but am trying to put it in to a function instead of repeating it in each script.

Individually, the lines in this function work, however when run as a function, the script does not encounter errors, but I don't get any result.

If anyone can spot what I'm missing in this, I'd greatly appreciate it.

            Function Invoke-AsUser() {
            Param(
                [Parameter(Mandatory=$true)]
                [String]
                $ScriptBlock
                ,
                [Parameter(Mandatory=$true)]
                [String]
                $RunAsUser
                ,
                [Parameter(Mandatory=$true)]
                [String]
                $RunAsPassword
                ,
                [Switch]$credSSP=$false
                )

                #Get the execution policy and store
                    $ExecutionPolicy = Get-ExecutionPolicy
                #Set up WSMANCredSSP
                    Enable-WSManCredSSP -Role Server -Force | out-null
                    Enable-WSManCredSSP -Role Client -DelegateComputer $env:COMPUTERNAME -Force | Out-Null
                #Set WSMAN MaxMemoryPerShell
                    #The following Prevents "Out of memory" errors from occurring when running commands through a remote pssession.
                    set-item wsman:localhost\Shell\MaxMemoryPerShellMB 512
                #Enable PSRemoting
                    try
                    {
                        enable-psremoting -force | Out-Null
                    }
                    catch
                    {
                        Write-Host "Enabling PSRemoting returned a non fatal exception."            
                    }
                #Create Credentials
                    $cred = new-object System.Management.Automation.PsCredential($runasuser,(ConvertTo-SecureString $RunasPassword -AsPlaintext -force))
                    $cred

                #Create the pssession
                    If ($credSSP -eq $true) {
                            try {
                                write-host "Authenticating with CredSSP"
                                $s = new-pssession -ComputerName $ENV:COMPUTERNAME -Credential $cred -Authentication Credssp
                            }

                            Catch {
                                    Write-Error "Creating new-pssession failed"
                            }
                        }
                    Else {
                            try {
                                    Write-Host "Authenticating without CredSSP"
                                    $s = new-pssession -ComputerName $ENV:COMPUTERNAME -Credential $cred
                                }

                                Catch {
                                        Write-Error "Creating new-pssession failed"
                                }
                        }

                #Invoke the command using pssession
                    Write-host "Running Scriptblock as $RunAsUser"
                    Invoke-Command -Session $s -ScriptBlock {Set-executionpolicy Bypass -Force}
                    Write-Host $ScriptBlock
                    invoke-command -Session $s -ScriptBlock { $ScriptBlock }
                    Write-host "Running Scripblock as $RunAsUser has finished."

                #set executionpolicy back to original
                    $ScriptBlock = "Set-ExecutionPolicy $ExecutionPolicy -Force"
                    Invoke-Command -Session $s -ScriptBlock {$ScriptBlock}

                #Disable psremoting
                    Disable-PSRemoting -force -WarningAction SilentlyContinue
            }

            $ErrorActionPreference = "Stop"
            Invoke-AsUser -ScriptBlock "& C:\temp\test.ps1" -RunAsUser $ENV:RUNASUSER -RunAsPassword $ENV:RUNASPASSWORD -CredSSP
user3255401
  • 135
  • 1
  • 1
  • 8

2 Answers2

0

Remove the "|out-null" from your script and you should get better debugging output.

  • Thanks. I had removed |out-null while debugging but cleaned it up for posting here. – user3255401 Mar 06 '14 at 03:18
  • I have figured out where the problem lies, but not a solution to it. It turns out that the Function Argument "Scriptblock" is not being passed in to the line invoke-command -Session $s -ScriptBlock { $ScriptBlock } If I change the line to be invoke-command -Session $s -Filepath $filepath it works. However this limits the functionality as I cannot pass in arguments to the script in $filepath. – user3255401 Mar 06 '14 at 03:21
  • Try changing the parameter type to [scriptblock] and then pass the parameter directly e.g. `-Scriptblock $scriptblock`. – Keith Hill Mar 06 '14 at 04:40
  • Keep in mind that the invoke-command scriptblock is completely isolated memory space. So if you try an invoke a script-level variable inside that scriptblock, you'll fail when your $scriptblock variable gets interpreted as $null. You could probably pass your scriptblock as an argument to the invoke-command scriptblock, but I typically just write a script that's totally self-contained inside that scriptblock. – esoterydactyl Mar 06 '14 at 04:41
0

I have this figured out.

Invoke-Command expects an argument of type "System.Management.Automation.ScriptBlock" however was receiving a system.string.

The error I got when I dug a little deeper was: Cannot process argument transformation on parameter 'ScriptBlock'. Cannot convert the " echo "hello" " value of type "System.String" to type "System.Management.Automation.ScriptBlock".

To solve this, I added the following line:

        #Creating a system.management.automation.scriptblock object from a string
        $ScriptObj = ([ScriptBlock]::Create($ScriptBlock))
        Invoke-Command -Session $s -ScriptBlock $ScriptObj

Everything works now as I would want.

user3255401
  • 135
  • 1
  • 1
  • 8