VeeDub Posted January 30 Share Posted January 30 (edited) 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 January 30 by VeeDub Link to comment Share on other sites More sharing options...
VeeDub Posted January 30 Author Share Posted January 30 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 More sharing options...
argumentum Posted January 30 Share Posted January 30 (edited) Run it as in the example https://www.autoitscript.com/autoit3/docs/functions/StderrRead.htm Let me know it it worked. Or, use this RunWaitEx(). Edited January 30 by argumentum more VeeDub 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
VeeDub Posted January 30 Author Share Posted January 30 @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. argumentum 1 Link to comment Share on other sites More sharing options...
VeeDub Posted January 31 Author Share Posted January 31 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. argumentum 1 Link to comment Share on other sites More sharing options...
VeeDub Posted January 31 Author Share Posted January 31 I have found this Start-Transcript -Path "Drive:\Folder\Transcript.txt" ## YOUR EXISTING CODE ## Stop Transcript Am going to try it. argumentum 1 Link to comment Share on other sites More sharing options...
argumentum Posted January 31 Share Posted January 31 ;~ 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 VeeDub 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
VeeDub Posted January 31 Author Share Posted January 31 I think I will try your suggestion instead. If nothing else I will be able to query the return code if the behaviour continues. Thanks! argumentum 1 Link to comment Share on other sites More sharing options...
VeeDub Posted January 31 Author Share Posted January 31 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 More sharing options...
argumentum Posted January 31 Share Posted January 31 (edited) 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 January 31 by argumentum more VeeDub 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
argumentum Posted January 31 Share Posted January 31 (edited) ConsoleWrite(_RunWaitEx('powershell "if ($false) {''yup''} else {''nah''}" ') & @CRLF) Exit would work but I'd do that if/then/else in AutoIt. g'night Edited January 31 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
VeeDub Posted January 31 Author Share Posted January 31 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 More sharing options...
VeeDub Posted January 31 Author Share Posted January 31 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 More sharing options...
VeeDub Posted January 31 Author Share Posted January 31 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 More sharing options...
Solution VeeDub Posted January 31 Author Solution Share Posted January 31 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 More sharing options...
argumentum Posted January 31 Share Posted January 31 7 hours ago, VeeDub said: $sRet = _RunWaitEx('powershell "Get-VM -name ALR_CyberX_DR3-4"') $VmNamed = "ALR_CyberX_DR3-4" $sRet = _RunWaitEx('powershell "Get-VM -name ' & $VmNamed & '"') VeeDub 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
argumentum Posted February 2 Share Posted February 2 On 1/31/2024 at 12:04 AM, argumentum said: on Thursday/Friday when I get some time It's Friday. So, how did it go ?. All good ?. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
VeeDub Posted February 7 Author Share Posted February 7 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. argumentum 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now