0

We're working on protecting files with RMS in our environment. We have to use PowerShell.

I can't even use WDS server with MDT joined to the domain as the psxml files it uses aren't signed.

I have to run PS scripts as single line commands or as encoded commands using the [convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($code)) line with my script wrapped in $code = {}.

This script works when run from PowerShell ISE.

$lines = Get-Content E:\folder\list.txt | Select-String -Pattern "Success Message" -AllMatches -Context 1,0 | % $_.Context.PreContext[0]
    foreach ( $line in $lines ) {
        $file = $line.ToString().TrimStart("chars. ")
        Protect-RMSFile -File $file -InPlace -DoNotPersistEncryptionKey All -TemplateID "template-ID" -OwnerEmail "admin@domain.com" | Out-File -FilePath E:\folder\logs\results.log -Append
        }

Batch script:

"e:\folder\command.exe -switches" > "E:\folder\list.txt" 

powershell.exe -EncodedCommand encodedBlob

Output:

Cannot index into a null array.
At line:3 char:1
+ $lines = Get-Content E:\folder\list.txt | Select-String      -Pattern "S ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

I saw on another question an exception log of some sort may be of assistance...

$Error.Exception | Where-Object -Property Message -Like "Cannot index into a null array." | Format-List -Force | Out-File -FilePath E:\folder\err.log

Output:

ErrorRecord                 : Cannot index into a null array.
StackTrace                  :    at CallSite.Target(Closure , CallSite , Object , Int32 )
                             at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
                             at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
                             at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
                             at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
WasThrownFromThrowStatement : False
Message                     : Cannot index into a null array.
Data                        : {System.Management.Automation.Interpreter.InterpretedFrameInfo}
InnerException              : 
TargetSite                  : System.Object CallSite.Target(System.Runtime.CompilerServices.Closure, System.Runtime.CompilerServices.CallSite, System.Object, 
                              Int32)
HelpLink                    : 
Source                      : Anonymously Hosted DynamicMethods Assembly
HResult                     : -2146233087

Thinking it was something as simple as NTFS permissions, I took owner and replaced all permissions on this folder structure with admin and me full control. No change in the error.

Any tips? Am I overlooking something simple?

Mike
  • 3
  • 1
  • If it was a permissions issue, you would've hit an error in the `Get-Content` call. Your logic is bad for the pattern matching so `$Lines` ends up `$Null`. – Maximilian Burszley Dec 07 '17 at 20:36

1 Answers1

0

Your ForEach-Object call (% $_) doesn't make any sense and was causing the issue.

$Lines = Select-String -LiteralPath 'E:\folder\list.txt' -Pattern 'success\smessage' -AllMatches -Context 1,0

ForEach ($Line in $Lines.Context.PreContext)
{
    $File = $Line.TrimStart('chars. ')
    Protect-RMSFile -File $File -InPlace -DoNotPersistEncryptionKey 'All' -TemplateID 'template-ID' -OwnerEmail 'admin@domain.com' |
        Out-File -FilePath 'E:\folder\logs\results.log' -Append
}

One-liner-esque (suitable for encoding):

SLS 'success\smessage' 'E:\folder\list.txt' -AllMatches -Context 1,0 |
  % { Protect-RMSFile -File $_.Context.PreContext.TrimStart('chars. ') -InPlace -DoNotPersistEncryptionKey 'All' -TemplateID 'template-ID' -OwnerEmail 'admin@domain.com' |
  Out-File 'E:\folder\logs\results.log' -Append

In this example, I've utilized aliases and positionally-bound parameters to make the code shorter.

Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • Thank you. Your rewrite is working. Voted but too new for it to count. That's what I get for copying bits of scripts without fully understanding everything in them. The .Context.PreContext was apparently functional before encoding. Can you tell me how? I am trying to get better. – Mike Dec 07 '17 at 23:43
  • @Mike Which part are you trying to understand? I can expound if I know what you don't get – Maximilian Burszley Dec 08 '17 at 15:07
  • @Mike the `.Context.PreContext` is the line prior to the capture (due to `-Context 1,0`). Because there are multiple captures, it's an array, so you need to loop through them to interact with each one. I've added an alternate edit in my answer you can perform that should be the same. – Maximilian Burszley Dec 08 '17 at 15:10