Using PSHELL from TCSTART.BTM

Code:
     _x64: 1
   _admin: 1
_elevated: 1

TCC  25.00.20 x64   Windows 10 [Version 10.0.18362.356]
OS Name:                   Microsoft Windows 10 Pro
OS Version:                10.0.18362 N/A Build 18362
I have in my TCSTART.BTM;
Code:
  pshell /s "$vfp = new-object -com myserver.myclass"
  pshell /s "$vfp | get-member"
From a brand new start of TCMD/TCC (64-bit), the preceding returns;
Code:
pshell  /s "$vfp = new-object -com myserver.myclass"
PSHELL: System.Management.Automation.CmdletInvocationException : Retrieving the COM class factory for component with CLSID {E2C2C43A-B6C4-4053-B4AC-9C697034A08A} failed due to the following error: 80070005 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).
So, I start a TCMD/PowerShell (64-bit) tab, and try it from there;
Code:
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS E:\utils> $vfp = new-object -com myserver.myclass
PS E:\utils> $vfp | get-member


   TypeName: System.__ComObject#{00078a50-5ad0-4ec6-aa59-976b47734989}

Name    MemberType Definition
----    ---------- ----------
MyDoCmd Method     Variant MyDoCmd (string)
MyEval  Method     Variant MyEval (string)
Works as it should.

So, I start another new TCC (64-bit) tab in TCMD, which launches TCSTART.BTM;
Code:
pshell  /s "$vfp = new-object -com myserver.myclass"
pshell  /s "$vfp | get-member"


   TypeName: System.__ComObject#{00078a50-5ad0-4ec6-aa59-976b47734989}

Name    MemberType Definition
----    ---------- ----------
MyDoCmd Method     Variant MyDoCmd (string)
MyEval  Method     Variant MyEval (string)
This time, it works!

I close the PowerShell (64-bit) tab.

I can start as many new TCC (64-bit) tabs in TCMD, and the two commands will work from TCSTART.BTM

Close down TCMD, and start it again. Same problem.

I have tried this with several 64-bit COM .dlls, and the same thing happens. It seems that I have to use an actual PowerShell (64-bit) session to initially load the COM .dll, before it can be recognized in TCC (64-bit)

My solution to get this working via the TCSTART is to add a line preceeding the two PSHELL lines in TCSTART.BTM;
Code:
powershell -command "$vfp = new-object -com myserver.myclass"
Now, starting a new TCMD/TCC (64-bit) with TCSTART.BTM;
Code:
powershell -command "$vfp = new-object -com myserver.myclass"
pshell  /s "$vfp = new-object -com myserver.myclass"
pshell  /s "$vfp | get-member"


   TypeName: System.__ComObject#{00078a50-5ad0-4ec6-aa59-976b47734989}

Name    MemberType Definition
----    ---------- ----------
MyDoCmd Method     Variant MyDoCmd (string)
MyEval  Method     Variant MyEval (string)
...and it works as it should.

Posting this work-around mainly for my future reference.

Joe
 
While the PShell built-in has some quirks compared to the actual PowerShell, the availability of a persistent PowerShell interpreter from TCC (PShell) is more advantageous for me, as I can open COM servers, and keep them open, while I use them, instead of having to constantly open/close the COM servers if I were to use them via PowerShell.exe -command

For example;
Code:
e:\utils>powershell -command "$vfp = new-object -com myserver.myclass; $vfp.MyDoCmd('use e:\utils\orders.dbf'); $vfp.MyEval('reccount()')"
True
16
...versus...
Code:
pshell  /s "$vfp = new-object -com myserver.myclass"
From TCC, I can now use PSHELL to open a FoxPro .DBF;
Code:
pshell /s "$vfp.DoCmd('use e:\utils\orders.dbf')"
...then I can query the FoxPro .DBF for the number of records it contains;
Code:
e:\utils>pshell /s "$vfp.Eval('reccount()')"
16
Joe