question

DavidMarino-1836 avatar image
0 Votes"
DavidMarino-1836 asked DavidMarino-1836 commented

PowerShell Script Fails When Run via Task Job

I setup a PS script some time ago to login to a remote server and map a drive to a folder in the remote server. This script is currently being used, so I know it works in my environment.
I now need to monitor a folder on the remote server, so I took the appropriate code snippet from my original PS script to use in my folder monitoring script. I can run this new file monitoring script manually without any problems, but when I attempt to schedule it to run from the task scheduler I get the error:
Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "password" is null. Change the value of argument "password" to a non-null value."

I can manually execute each line of code leading up to and including $credential = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $password
without any errors. So I'm not quite sure why I can't run the script via the task scheduler, which is how all the other scripts using my connection code are being executed successfully.
When I attempt to display the $password variable after it's populated with password info ($password = Get-Content -Path $psScript\"cpswd.txt" | ConvertTo-SecureString) I get System.Security.SecureString, which I believe is correct.

I have uploaded my script, any guidance is greatly appreciated as I'm stumped at the moment.

190627-monitorpscript.txt


windows-serverwindows-server-powershell
monitorpscript.txt (4.0 KiB)
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

How are you able to "manually execute each line of code" if it's running as a scheduled task?

I'd start by adding a Start-Transcript at the beginning of the script and a Stop-Transcript at the end. Then sprinkle Write-Host cmdlets to add content to the transcript whenever a variable changes. The 1st Write-Host I'd add is something like this:

 Write-Host "Password: " (Get-Content -Path $psScript\"cpswd.txt")

0 Votes 0 ·

@RichMatheisen-8856
Through the PS ISE / IDE, (after opening the script) I would either cut & paste in the console window or right click on the line and RUN SELECTION F8, either way the line is executed in the ISE console window.
In my troubleshooting efforts I did write out to a file each step ensuring that I was in the right folder to read the password file, as well as ensuring the variables were not null. The Get-Content of the cpswd.txt file returns a long string.

As far as I can tell I'm in the right folder, the password file has data, the variable $password is identified as a System.Security.SecureString, it should work as this portion is no different than the in PROD version.
Also while in the ISE I can hit the Run Script button and it works as expect. When it fails via the Task Scheduler an email is generated and sent to me, this doesn't happen when I manually run the script.
In addition, I opened a PS console and executed the script without any issues.

I'm logging into the local server to perform this work, dev, running, etc. The task job is setup to run with the highest privilege, using the same service ID that all the other jobs use.

Thank you for the help.

0 Votes 0 ·

When you added the transcript to the code, and the write-host cmdlets, what did you see in the transcript file that doesn't look right?

0 Votes 0 ·
DavidMarino-1836 avatar image
0 Votes"
DavidMarino-1836 answered

@RichMatheisen-8856
I'm attaching the log file in which I record the execution of the cmdlets manually and via the task scheduler; each is noted in the file.

The Task Scheduler version errors out right after the New-Object System.Management.Automation.PSCredential -ArgumentList $username, $password execution.
The error in the email is Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "password" is null. Change the value of argument "password" to a non-null value.".

That is all the information that is provided.
I also did a if statement "if ($password -eq $null) { "write out to file $password is null"}". This is executed via the Task scheduler, but not when I kick off the script manually.
At this point I don't know if anything has been updated on the server by Admin that would cause this issue190617-04062022-logfile.txt. This is a test server. I could try running it on the prod server since it's not a data changing script.



5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered DavidMarino-1836 commented

It seems you're opposed to adding a transcript to you script. Is there a reason for that?

I don't see how what you're doing with that password ever works!

 $pw = "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000030da7b3fadcf6740a49b4f31f1dda6b10000000002000000000003660000c00000001000000005780f7baac79ee44295a9bd2aa31e370000000004800000a0000000100000000718ad40bb416d7d72426294c88d278718000000a8e7e564efd8902cdc166efd59f1b752f6466050077a4ea814000000b3e496f27b8eb4e7967f89116e53b5946dfd7c00"
 $password = $pw | ConvertTo-SecureString
 $username = "melvin"
 $credential = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $password

That code throws TWO errors:

 ConvertTo-SecureString : Key not valid for use in specified state.
 At C:\Junk\Untitled-22.ps1:2 char:19
 + $password = $pw | ConvertTo-SecureString
 +                   ~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException
     + FullyQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.ConvertToSecureStrin  
    gCommand
    
 New-Object : Exception calling ".ctor" with "2" argument(s): "Cannot process argument because the value of argument "password" is       
 null. Change the value of argument "password" to a non-null value."
 At C:\Junk\Untitled-22.ps1:4 char:15
 + ... redential = New-Object System.Management.Automation.PSCredential -Arg ...
 +                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodInvocationException
     + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

How did you get the 300+ characters in that file? Did you copy it from another machine? If you did, that not going to work because the encrypted string is created using the certificate on the machine that did the encryption.

· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@RichMatheisen-8856
Apologies I didn't understand your Transcript comment. This is the first time I'm aware of this cmdlet, but I will incorporate this cmdlet in the morning, and report back then on the results.
Regarding the TWO Errors you mention:
1. I don't get an "ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.ConvertToSecureStrin
gCommand" Error at any time.


  1. The 2nd error you display appears to be the one I'm getting when running the script via the task scheduler. I'm not sure if you're getting the 2nd because of the 1st error. I did not copy the password file for the reason you mentioned. I (re) generated the password file for this particular solution.

My original solution, and the one that I deployed in PROD was derived through a google search. I have created multiple variations of this solution (i.e. connect to remote Windows system) without any issues before. Out of frustration I rewrote the pscript over again, no cut & paste just to be sure it wasn't some weird file related issue. For all intent and purposes, except for it being a new file, everything else is the same. The same external server, the same code syntax, the same flow of execution.

Lastly, I manually kicked off the job. If it records the changes in the folder, which I hope and expect, then I can only conclude that the issue is external to the script. keeping my fingers crossed.

/r
dm



0 Votes 0 ·

191014-snag-322dc035.png



Manual Run w/o change to credential method
Windows PowerShell transcript start
Start time: 20220407082948
Username: ###\<my ID>
RunAs User: ###\<my ID>
Machine: <Test Server> (Microsoft Windows NT 10.0.14393.0)
Host Application: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Process ID: 15792
PSVersion: 5.1.14393.4583
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.14393.4583
BuildVersion: 10.0.14393.4583
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1


Transcript started, output file is F:\Apps\FolderMonitoring\Logs\04072022_Transcript.txt

Id Name PSJobTypeName State HasMoreData Location Command


1 621c6844-2d0... NotStarted False $path = $Event.Source...
2 b715dd87-b65... NotStarted False $path = $Event.Source...
3 57d9c52b-b23... NotStarted False $path = $Event.Source...
4 a0b95dbe-be1... NotStarted False $path = $Event.Source...



0 Votes 0 ·
snag-322dc035.png (71.3 KiB)
RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered DavidMarino-1836 commented

The System.Management.Automation.PSCredential class constructor that takes two arguments requires them to be a System.String object containing the user name, and a System.Security.SecureString object containing the encrypted password. the object type of the second argument is, in your case, System.String (a plain text string of characters).

I think a much better way to do this is to create the credential object and export it:

 $credential = Get-Credential
 $credential | Export-CliXml -Path 'C:\My\Path\cred.xml'

Then, in the script that needs the credential, import that saved file:

 $credential = Import-CliXml -Path 'C:\My\Path\cred.xml'

No need to mess around with strings, secure strings, and creating credentials using .Net class constructors. It's a lot more readable, too.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@RichMatheisen-8856
I incorporated both your Start-Transcript and Get-Credential methodology, and ran the script manually and via the Task Scheduler; four test cases. In all cases the results are the same.
190945-04072022-transcriptts.txt191003-04072022-transcripttsimport.txtManually it works okay regardless of the credential encoding and via the TS it always fails. I'm uploading the transcript logs. Any file with TS is the result of the Task Scheduler and Import is using the credential method you provided.



I will upload the other two in a new comment... System appears not to let me upload more than two

0 Votes 0 ·