Jump to content

Intermittent problem running Powershell scripts


Go to solution Solved by VeeDub,

Recommended Posts

Hello,

I have an AutoIt script that automates tasks with Hyper-V VMs.

Some of these tasks, like turning on and turning off the VM are performed using Powershell, which I'm calling from within AutoIt.

Here is a Powershell script:

Turn_on_VM.ps1

$VMName = "ALR_testclient3"
Start-VM -VMName $VMName

Here is how I call the Powershell script

runPowershellScript('C:\ZEN\ALR\Turn_On_VM.ps1')

Func runPowershellScript($sScript)

    RunWait("powershell.exe -ExecutionPolicy Bypass -File " & $sScript, "", @SW_HIDE)

EndFunc

I run the AutoIt script daily and what I'm finding is that 4 - 5 days per week, the script works fine.

Then on the "off days", the Powershell scripts are clearly not executing as expected.

The AutoIt script is running on Windows Server 2019.

The script is compiled as x64.

I am specifying:

#RequireAdmin

After suggestions on thing to try to make the AutoIt script robust.

Is there another way to execute the Powershell scripts?

Thanks
VW

Edited by VeeDub
Link to comment
Share on other sites

One option I've thought of, is there a way that I can log Powershell output when a script is executed?

Presumably when the scripts are not executing as expected, some error condition has arisen and hopefully some error message is being generated.

If I can capture that, then I'll have some insight as to what is going on.

Link to comment
Share on other sites

@argumentum

Thanks for sharing.

I have replaced my function with _RunWaitEx

I've watched the first calls to the function and the powershell is executing as it should.

Which is not unlike my function most of the time.

Hopefully _RunWaitEx just works.

But if we get the same behaviour that I've been observing some of the time, I've also added some logging for:

UpdateEventLog("@error: " & @error)
UpdateEventLog("Exitcode: " & @extended)
UpdateEventLog("Exitcode: " & $iExitCode)
UpdateEventLog("Output: " & $sOutput)

Which will hopefully give me some idea what is going on.

 

 

Link to comment
Share on other sites

Unfortunately the issue still exists.

Ran the AutoIt program yesterday, 5 VM's were managed, so that means there were 15 Powershell script operations and all completed correctly.

Ran the AutoIt program today, and on the 5th VM, the second Powershell script did not update correctly.

The second Powershell script is supposed to update the VM boot device. 

In this instance this didn't happen.

I call this Powershell script 5 times, because since I've become aware of this issue, I'm trying to work out a way to ensure that the script actions are performed.

So the script was called 5 times, but didn't update the boot device.

No errors were reported.

2024-01-31 Wed 11:12 Set VM boot device to DVD
2024-01-31 Wed 11:12 @error: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Output: 
2024-01-31 Wed 11:12 @error: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Output: 
2024-01-31 Wed 11:12 @error: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Output: 
2024-01-31 Wed 11:12 @error: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Output: 
2024-01-31 Wed 11:12 @error: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Exitcode: 0
2024-01-31 Wed 11:12 Output:

The logging above is identical to the logged entries when the boot device has been successfully updated for earlier VM's.

Link to comment
Share on other sites

;~  Local $sRet = _RunWaitEx('powershell "Get-VMHost | Select-Object * | ConvertTo-CSV"')
;~  Local $sRet = _RunWaitEx('powershell "Get-VMHost | Select-Object * | ConvertTo-JSON"')
;~  Local $sRet = _RunWaitEx('powershell "get-vm | Select-Object *  | ConvertTo-CSV"') ; <<<<
;~  Local $sRet = _RunWaitEx('powershell "Get-VMDvdDrive -VmName * | Select-Object *  | ConvertTo-CSV"') ; <<<<
;~  Local $sRet = _RunWaitEx('powershell "Get-VMHardDiskDrive -VmName * | Select-Object *  | ConvertTo-CSV"') ; <<<<
;~  Local $sRet = _RunWaitEx('powershell "get-vm | Select-Object *  | ConvertTo-JSON"')
;~  Local $sRet = _RunWaitEx('powershell "Get-VMSnapshot -VmName * | Select-Object * | ConvertTo-CSV"') ; <<<<<
;~  Local $sRet = _RunWaitEx('powershell ' & '"Get-VMHardDiskDrive -VMId ''a069108d-c6fd-4385-a817-c1c4cf4f5fa5''  | Select-Object *  | ConvertTo-CSV"') 
;~  Local $sRet = _RunWaitEx('powershell ' & '"Get-VMHardDiskDrive -VMName ''New Virtual Machine''  | Select-Object *  | ConvertTo-CSV"')

You can run things like this. No need to run PS1 files and actually I prefer to avoid them.
The above is something I started some time ago and never continued but do remember that was better to skip the PS1s, if I was gonna use AutoIt for the logic anyway. My 2 cents

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

I'm having some trouble converting a Powershell script to _RunWaitEx syntax

Here is an example

$VMName = "ALR_3-4"
$VM = Get-VM -name $VMName -ErrorAction SilentlyContinue
if (!$VM) { 
Write-Host "No VM named: $VMName exists" 
"No VM named: $VMName exists" | Out-File -FilePath C:\ZEN\ALR\VM_Not_Found.txt}
else
{ Write-Host "A VM named: $VMName already exists" 
"A VM named: $VMName already exists" | Out-File -FilePath C:\ZEN\ALR\VM_Exists.txt}

I think I will need to build a command string and then pass that to _RunWaitEx

Local $Command = 'powershell "$VMName = " & $ALR_Host_VM & 

Local $sRet = _RunWaitEx($Command)

But I'm not sure how to convert the multi-line powershell script arguments to a _RunWaitEx call

Link to comment
Share on other sites

You've got the examples in my prior posts. All the if/then/else I did in AutoIt. I'd run a command, get the result and take it from there.
The Local $Command = 'powershell "$VMName = " & $ALR_Host_VM & should be
Local $Command = 'powershell "$VMName = ' & $ALR_Host_VM & ' " '.
Pay attention to the " and ' characters.

'"Get-VM -name ''$VMName''"
the  -ErrorAction SilentlyContinue I would not add. Because you'd handle the if/then/else in AutoIt, else just run PS1s.  =/

Or explain what is that you'd like to have and I'll look at coding it on Thursday/Friday when I get some time to try out stuff.

Edited by argumentum
more

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

The problem that I have is that all the examples are hardcoded, that is, the example code is "fixed".

Whereas all my powershell snippets / functions are designed to work on a VM and the VM is  a variable.

So, I don't see how I can use the examples that you posted, unless I was to write 5 individual versions (for the 5 VM's that I'm automating now. But that approach is not desirable as the VM's will change in the future.

So, what I would want to do is build a command string - where I can alter the powershell commands dynamically (i.e. change the VM that is being referenced).

But I have tried doing that, and while the argument looks fine to me. It is not being accepted.

This is what I mean

Local $sRet

    $Command1 = "'" & "powershell "
    $Command2 = """" & "Get-VM -name "
    $Command3 = $ALR_Host_VM & """" & "'"

    $Command = $Command1 & $Command2 & $Command3

    ConsoleWrite("Command: " & $Command & @CRLF)
    $sRet = _RunWaitEx($Command)

    ConsoleWrite("$sRet: " & $sRet & @CRLF)

Command: 'powershell "Get-VM -name ALR_CyberX_DR3-4"'
$sRet: ''powershell' is not recognized as an internal or external command,
operable program or batch file.

But if I do a hard-coded argument, the call works.

Local $sRet

#cs
    $Command1 = "'" & "powershell "
    $Command2 = """" & "Get-VM -name "
    $Command3 = $ALR_Host_VM & """" & "'"

    $Command = $Command1 & $Command2 & $Command3

    ConsoleWrite("Command: " & $Command & @CRLF)
#ce
    $sRet = _RunWaitEx('powershell "Get-VM -name ALR_CyberX_DR3-4"')

    ConsoleWrite("$sRet: " & $sRet & @CRLF)

$sRet: 
Name             State   CPUUsage(%) MemoryAssigned(M) Uptime           Status             Version
----             -----   ----------- ----------------- ------           ------             -------
ALR_CyberX_DR3-4 Running 0           4096              01:32:18.8370000 Operating normally 9.0

The arguments looks identical to me in the two calls.

Powershell is a PITA

Link to comment
Share on other sites

6 hours ago, VeeDub said:

I have found this

Start-Transcript -Path "Drive:\Folder\Transcript.txt"
## YOUR EXISTING CODE ##
Stop Transcript

Am going to try it.

Because perhaps I'm not going to be able to call Powershell directly in AutoIt, which would be my preference.

I'm exploring a few other options.

This transcript option is useless, it doesn't log anything that is relevant.

Link to comment
Share on other sites

I've done some Google searching on issues with calling Powershell scripts and there are others that have had issues.

One work-around that somebody reported as being effective, was calling the Powershell script via a batch file.

That is not hard for me to test, so I am trying that in the meantime.

Link to comment
Share on other sites

  • Solution

I don't know yet whether using bat files to call the Powershell scripts is going to be more reliable (and ultimately that will be what matters).

But one advantage of using bat files is that the bat files play very nicely with the logging in _RunWaitEx

2024-01-31 Wed 22:04 @error: 0
2024-01-31 Wed 22:04 Exitcode: 0
2024-01-31 Wed 22:04 Exitcode: 0
2024-01-31 Wed 22:04 Output: 
C:\Users\AMR\AppData\Local\Temp\2>powershell -ExecutionPolicy Bypass -File C:\ZEN\ALR\Check_if_VM_Exists.ps1 
A VM named: ALR_CyberX_DR3-4 already exists

All of the bat files provide useful Output

Link to comment
Share on other sites

Using a bat file to call the Powershell script rather than a cmd file ended up being the resolution here.

That being said, if I were doing this again from scratch I would have a close look at @argumentum post here

I'm a fan of this approach.

However, in this instance as I already had the code "working" apart from intermittent glitches, just changing to using a bat file instead of a cmd file was easier.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...