Starting *.xlsm?

May 20, 2008
10,573
78
Syracuse, NY, USA
This is a rehash of a thread from December 2019.

V:\FURNACE.XLSM exists. At a CMD or PowerShell command line, "v:\furnace.xlsm" causes Excel to start, opening the xlsm file. It doesn't matter how CMD/PowerShell was started (from TCC or not). The same command line, issued to TCC, results in

Code:
v:\> v:\Furnace.xlsm
TCC: (Sys) V:\Furnace.xlsm is not a valid Win32 application.
It doesn't matter how TCC was started (from CMD/PowerShell or not).

The string "v:\furnace.xlsm" also works as the command assigned to a PowerPro button or an AutoHotKey keystroke, and in the Start\Run and TaskMgr\NewTask dialogs.

In December 2019 I noted that "v:\furnace.xlsm" works in TCC v18 and fails in later versions and its working or not has nothing to do with elevation.
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
4,202
72
Albuquerque, NM
prospero.unm.edu
On my system, starting an .XLSM file at the command line opens it in Excel.

Code:
C:\> C:\Users\cdye\Desktop\Book1.xlsm

C:\>which C:\Users\cdye\Desktop\Book1.xlsm
C:\Users\cdye\Desktop\Book1.xlsm is associated with : C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE

C:\>ver /r

TCC  26.01.35 x64   Windows 10 [Version 10.0.17763.1098]
TCC Build 35   Windows 10 Build 17763
Registered to COE-LN00061392

C:\>
 
May 20, 2008
10,573
78
Syracuse, NY, USA
I see this.

Code:
v:\> which v:\Furnace.xlsm
v:\Furnace.xlsm is an external : V:\Furnace.xlsm

v:\> assoc .xlsm
.xlsm=

v:\> ver

TCC  26.01.35 x64   Windows 10 [Version 10.0.18363.778]
 
May 20, 2008
10,573
78
Syracuse, NY, USA
I also noticed this. I don't know if it's related. This line

Code:
ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL);
in a stand-alone EXE causes excel and the file to be opened.

Whereas, this line

Code:
TCError((INT) ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL), NULL);
in a plugin (v26) gives

Code:
TCC: (Sys) Access is denied.
 
May 20, 2009
287
5
56
ITALY
I see this.
...
v:\> assoc .xlsm
.xlsm=
...
I believe that this is why it does not work for You.
On my Windows 10 I see the following.
Code:
[C:\Program Files\JPSoft\TCMD26]assoc .xlsm
.xlsm=Excel.SheetMacroEnabled.12
[C:\Program Files\JPSoft\TCMD26]ftype Excel.SheetMacroEnabled.12
Excel.SheetMacroEnabled.12="C:\Program Files (x86)\Microsoft Office\Office16\EXCEL.EXE" /dde
Regards

Rodolfo Giovanninetti
 
May 20, 2008
10,573
78
Syracuse, NY, USA
I can successfully use the string "v:\furnace.xlsm" (to start Excel and open the named file) in the following places.

Start/run dialog
TaskMgr/NewTask dialog
PowerPro button
AutoHotKey keystroke
CMD command line
PowerShell command line
Notepad++'s Run/Run dialog
ProcessExplorer's File/Run dialog
My own EXE which uses ShellExecute()
My own EXE which uses ShellExecuteEx()

The only places (found so far) where it does not work are these.

TCC command line (not a valid Win32 application)
TCC command line with START (Access is denied)
TCC, ShellExecute/ShellExecuteEx in a plugin (Access is denied)
TCMD's Tabs/Run dialog (not a valid Win32 application)
 
May 20, 2008
10,573
78
Syracuse, NY, USA
What happens if You change assoc and ftype so that look like mine ones?

Regards

Rodolfo Giovanninetti
I don't know what you want me to do. I have Office 2019 Microsoft store version. I don't have "Excel.SheetMacroEnabled.12" (or anything like it). And I don't have "C:\Program Files (x86)\Microsoft Office\Office16\EXCEL.EXE. And, since it works OK EVERYWHERE except with JPSoft products, I don't think changing Office's set-up should be necessary.
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
4,202
72
Albuquerque, NM
prospero.unm.edu
How about simply associate .xlsm=%@search[excel.exe] or the like?

It seems to me you've demonstrated that your version of Office is using some form of file associations that TCC doesn't recognize. So, use the documented method.

("Excel.SheetMacroEnabled.12" is the filetype. It's essentially cosmetic. The filetype generated by ASSOCIATE is not as pretty, but should work just the same.)
 
May 20, 2008
10,573
78
Syracuse, NY, USA
How about simply associate .xlsm=%@search[excel.exe] or the like?

It seems to me you've demonstrated that your version of Office is using some form of file associations that TCC doesn't recognize. So, use the documented method.

("Excel.SheetMacroEnabled.12" is the filetype. It's essentially cosmetic. The filetype generated by ASSOCIATE is not as pretty, but should work just the same.)
Considering that it works in 10 other scenarios (all I tried so far) I don't think I should have to make changes to accommodate TCC.

And (I haven't mentioned it lately) it works OK with TCC v17 (and not with TCC v19) (ditto for "START furnace.xlsm").

One of the oddest things is that this (below) works in a stand-alone EXE and fails (access denied) in a TCC plugin

Code:
ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL);
while this works in both scenarios

Code:
ShellExecuteW(NULL, L"open", L"v:\\doggy.txt", NULL, NULL, SW_SHOWNORMAL);
 
May 20, 2009
287
5
56
ITALY
Code:
[F:\]> file.abc

[F:\]file.abc
TCC: (Sys) F:\file.abc is not a valid Win32 application.

[F:\]assoc .abc
TCC: File association not found for extension ".abc"

[F:\]assoc .xlsm
.xlsm=Excel.SheetMacroEnabled.12

[F:\]ftype Excel.SheetMacroEnabled.12
Excel.SheetMacroEnabled.12="F:\Program Files\Microsoft Office\Office14\EXCEL.EXE" /dde
I have been able to reproduce this situation using a file whose suffix/extension is not associated to anything.
This on two systems, with two different versions of Windows, Office and TCC.
If on Your pc You type "ftype Excel.SheetMacroEnabled.12" what do You get?
And if You type "assoc .xlsm=Excel.SheetMacroEnabled.12" does it fix this issue for You?

Regards

Rodolfo Giovanninetti
 

rconn

Administrator
Staff member
May 14, 2008
11,910
133
Not reproducible here; I have no problem starting *.xlsm files from the command line. (Using Office 365, stock installation.)

Code:
[D:\TakeCommand26\TCConsole]assoc .xlsm
.xlsm=Excel.SheetMacroEnabled.12

[D:\TakeCommand26\TCConsole]ftype Excel.SheetMacroEnabled.12
Excel.SheetMacroEnabled.12="C:\Program Files (x86)\Microsoft Office\Root\Office16\EXCEL.EXE" "%1"
If TCC doesn't recognize a file extension, it looks for the file association. If that fails, TCC calls ShellExecute and leaves it up to Windows.
 
May 20, 2008
10,573
78
Syracuse, NY, USA
Not reproducible here; I have no problem starting *.xlsm files from the command line. (Using Office 365, stock installation.)

Code:
[D:\TakeCommand26\TCConsole]assoc .xlsm
.xlsm=Excel.SheetMacroEnabled.12

[D:\TakeCommand26\TCConsole]ftype Excel.SheetMacroEnabled.12
Excel.SheetMacroEnabled.12="C:\Program Files (x86)\Microsoft Office\Root\Office16\EXCEL.EXE" "%1"
If TCC doesn't recognize a file extension, it looks for the file association. If that fails, TCC calls ShellExecute and leaves it up to Windows.
Why do I get this?

Code:
v:\>  Furnace.xlsm
TCC: (Sys) V:\Furnace.xlsm is not a valid Win32 application.
As I said twice before, this line of code works in a stand-alone EXE and fails (access denied) in a plugin (ditto for ShellExecuteEx).

Code:
ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL);
I suppose it's failing in TCC too. WHY?????

I can't explain any of it but here's how the store version of Office 2019 does things.

Code:
v:\> regdir /v /d hkcr\.xlsm
hkcr\.xlsm
  OpenWithProgids
    AppXdns5t4sbkxjyz6eb2qq4r5mj353pd9gy : REG_NONE :

v:\> regdir /v /d hkcr\AppXdns5t4sbkxjyz6eb2qq4r5mj353pd9gy\Shell\open
hkcr\AppXdns5t4sbkxjyz6eb2qq4r5mj353pd9gy\Shell\open
  AppUserModelID : REG_SZ : Microsoft.Office.Desktop_8wekyb3d8bbwe!Excel
  PackageRelativeExecutable : REG_SZ : Office16\EXCEL.exe
  Parameters : REG_SZ : "%1"
  ContractId : REG_SZ : Windows.File
  DesiredInitialViewState : REG_DWORD : 0
  PackageId : REG_SZ : Microsoft.Office.Desktop.Excel_16051.12228.20364.0_x86__8wekyb3d8bbwe
  command
    DelegateExecute : REG_SZ : {BFEC0C93-0B7D-4F2C-B09C-AFFFC4BDAE78}
 
May 20, 2008
10,573
78
Syracuse, NY, USA
You gotta love Raymond!

I dunno.

My stand-alone EXE in which ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL) works does not call CoInitialize (or CoInitializeEx) at all.

The "ThreadingModel" for DelegateExecute : REG_SZ : {BFEC0C93-0B7D-4F2C-B09C-AFFFC4BDAE78} is "Apartment". Calling CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) does not get it to work in a plugin with either ShellExecute or ShellExecuteEx. I also tried COINIT_MULTITHREADED to no avail.
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
4,202
72
Albuquerque, NM
prospero.unm.edu
You gotta love Raymond!

I dunno.

My stand-alone EXE in which ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL) works does not call CoInitialize (or CoInitializeEx) at all.

The "ThreadingModel" for DelegateExecute : REG_SZ : {BFEC0C93-0B7D-4F2C-B09C-AFFFC4BDAE78} is "Apartment". Calling CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) does not get it to work in a plugin with either ShellExecute or ShellExecuteEx. I also tried COINIT_MULTITHREADED to no avail.
I don't think you can re-initialize COM in a plugin. I'm pretty sure that TCC initializes it for you, and you can't change the threading model on the fly. ('Cause that would be Bad.)

Of course, I could be completely wrong about any or all of this.
 
May 20, 2008
10,573
78
Syracuse, NY, USA
You were onto something, Charles ... but what? ... who knows..

I said a few times that ShellExecute/ShellExecuteEx to "open" an XLSM file fails in a plugin. Either one succeeds in a plugin if I first CoUninitialize(). For example,

Code:
    CoUninitialize();
    ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL);
    //SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO), 0, NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL, 0};
    //ShellExecuteEx(&sei);
That said, I cannot make it fail in a stand-alone EXE regardless of whether or not, or how, I call CoInitialize[Ex].

It's all very strange! As I said before, it only affects Office (2019, store) files.

I'm curious ... Rex, how does TCC CoInitialize for the thread in which plugins run?
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
4,202
72
Albuquerque, NM
prospero.unm.edu
For the record, ShellExecuteW() in a plugin works fine to open .XLSM files here:

Code:
C:\>which shellexec
shellexec is a plugin command (ShellExec)

C:\>shellexec desk:book1.xlsm
hWnd       = NULL
Verb       = NULL
Filename   = "C:\Users\cdye\Desktop\book1.xlsm"
Params     = NULL
Directory  = NULL
ShowCmd    = SW_SHOWNORMAL

Success.

C:\>
 
May 20, 2008
10,573
78
Syracuse, NY, USA
It gets even stranger! As I just said, this works in a plugin.

Code:
    CoUninitialize();
    ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL);
And thereafter, TCC seems to start normally and can successfully execute "v:\furnace.xlsm" and "START v:\furnace.xlsm".

If instead, if, in a plugin (InitializePlugin) I just

Code:
CoUnitialize()
then (ready for this?) I get a UAC prompt when I start TCC. If I say "OK" at the UAC prompt, TCC starts normally (and can execute or START the XLSM file). If I say "No" at the UAC prompt I get the "unregistered" dialog ... register ... "registration was successful" ... OK ... then I'm back to the unregistered dialog ... over and over again!
 
May 20, 2008
10,573
78
Syracuse, NY, USA
I'm not making this up. I've tested it several times. With CoUninitialize() alone in a plugin, things get screwy (UAC prompt ... as described earlier). With CoUnitialize() followed by a ShellExecute() (also as described earlier) things don't get screwy. I can't make sense of it!
 
May 20, 2008
10,573
78
Syracuse, NY, USA
And with this in InitializePlugin,

Code:
    CoUninitialize();
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
things seem just fine. I can "v:\furnace.xlsm", "START v:\furnace.xlsm", and "SHELLEX v:\furnace.xlsm" (plugin). I'll leave it that way for a while and see if anything breaks.
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
4,202
72
Albuquerque, NM
prospero.unm.edu
Perhaps ShellExecute() does a CoInitialize() for you, if it needs COM and you haven't done so already.

Anyway, I would expect things to break if you call CoUninitialize(). TCC probably isn't expecting to have COM jerked out from under it.
 
May 20, 2008
10,573
78
Syracuse, NY, USA
And with this in InitializePlugin,

Code:
    CoUninitialize();
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
things seem just fine. I can "v:\furnace.xlsm", "START v:\furnace.xlsm", and "SHELLEX v:\furnace.xlsm" (plugin). I'll leave it that way for a while and see if anything breaks.
That didn't take long. With those two lines in InitializePlugin, WMIQUERY is broken (access denied).
 
May 20, 2008
10,573
78
Syracuse, NY, USA
Perhaps ShellExecute() does a CoInitialize() for you, if it needs COM and you haven't done so already.

Anyway, I would expect things to break if you call CoUninitialize(). TCC probably isn't expecting to have COM jerked out from under it.
But I was re-initializing (APARMENTTHREADED) right after that.
 
Aug 23, 2010
581
7
Just one note…
This line
C:
ShellExecuteW(NULL, L"open", L"v:\\furnace.xlsm", NULL, NULL, SW_SHOWNORMAL);
Has a glaring issue that is not immediately obvious.

I know, this stuff is plastered all over the internet, and actual information is hard to come by… even help file doesn't quite help…
lpOperation

  • Pointer to a null-terminated string that specifies the operation to perform. The following operation strings are valid:
    …blabla…
    The lpOperation parameter can be NULL. In that case, the function opens the file specified by lpFile.
However, "opens" is NOT quite true. In reality, specifying NULL as lpOperation(lpVerb) will cause ShellExecute** to invoke DEFAULT action. Which is, unsurprisingly, not always "open".

Translation: explicitly specify lpOperation(lpVerb) only if you actually really definitely mean it. In all other cases, let the shell do its magic.
 
May 20, 2008
10,573
78
Syracuse, NY, USA
Since "access denied" seems to be central to this issue, I wondered if CoInitializeSecurity (which I know absolutely nothing about) might have something to do with it. I found a sample of its use (from Microsoft). It's rather default-ish and used below. When I put the code below in a plugin's InitializePlugin, things work well (so far). TCC can execute an XLSM file, it can START an XLSM file, and my plugin SHELLEX works on an XLSM file. There's no start-up or registration weirdness as there was in some earlier tests. And WMI stuff (which uses COM) works. Does anyone know what else in TCC uses COM? I'd like to test more. Here's the code. I wonder how it compares to what TCC does.

Code:
    CoUninitialize();
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    CoInitializeSecurity(
        NULL,                       // security descriptor
        -1,                          // use this simple setting
        NULL,                        // use this simple setting
        NULL,                        // reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // authentication level  
        RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level
        NULL,                        // use this simple setting
        EOAC_NONE,                   // no special capabilities
        NULL);                          // reserved