尝试构建XLL“该程序无法在DOS模式下运行”

8

我一直在尝试构建一个简单的XLL,只需要创建一个带有硬编码命令行的进程。以下是我的代码:

#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH: {
        LPSTARTUPINFOA si = new STARTUPINFOA();
        LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION();
        CreateProcessA(NULL, (LPSTR)"notepad.exe", NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, si, pi);
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

基本上是创建一个 DLL,然后将其重命名为 XLL。我正在使用 Visual Studio 2019,以下是我的编译标志:

/JMC /permissive- /Yu"pch.h" /ifcOutput "x64\Debug\" /GS /W3 /Zc:wchar_t /ZI /Gm- /Od /sdl /Fd"x64\Debug\vc142.pdb" /Zc:inline /fp:precise /D "_DEBUG" /D "EVIL_EXPORTS" /D "_WINDOWS" /D "_USRDLL" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MT /FC /Fa"x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Fp"x64\Debug\Evil.pch" /diagnostics:column 

我也使用专业的Excel 2013 64位版本。可能出了什么问题?我甚至尝试过Excel 2016 64位版本和Office 365。版本16.01。

更新: 基本上,这个语句可能应该出现在Excel电子表格中,但我至少希望“notepad.exe”能够运行,但这并没有发生。

以下是链接器标志:

/OUT:"C:\Users\Cristi Cretan\source\repos\XLLCalc\Release\XLLCalc.xll" /MANIFEST /LTCG:incremental /NXCOMPAT /PDB:"C:\Users\Cristi Cretan\source\repos\XLLCalc\Release\XLLCalc.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /IMPLIB:"C:\Users\Cristi Cretan\source\repos\XLLCalc\Release\XLLCalc.lib" /DEBUG /DLL /MACHINE:X86 /OPT:REF /SAFESEH /INCREMENTAL:NO /PGD:"C:\Users\Cristi Cretan\source\repos\XLLCalc\Release\XLLCalc.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"Release\XLLCalc.xll.intermediate.manifest" /LTCGOUT:"Release\XLLCalc.iobj" /OPT:ICF /ERRORREPORT:PROMPT /ILK:"Release\XLLCalc.ilk" /NOLOGO /TLBID:1 

一些猜测:可能是32位DLL和64位Office混合使用,或者反过来?否则,根据文档,XLL至少应该有一个xlAutoOpen导出。所以也许Excel缺少这个导出函数,因此会显示混淆的错误信息? - Sedenion
@Sedenion 不过,我所做的将 DLL 转换为 XLL 只是改名。但根据我在互联网上看到的,这不应该是一个问题。 - C. Cristi
@Sedenion 在他的电脑上,虽然电子表格中仍显示该消息,但至少打开了“calc.exe”。 - C. Cristi
打开XLL时,在Excel行中@user3840170。 - C. Cristi
1
通过将文件命名为XLL,Excel会认为它是一个插件,并寻找最少数量的入口点(请参阅Excel SDK)。这可能是一个措辞不当的错误,因为Excel不知道如何处理正在打开的文件。我不太清楚...如果您注释掉尝试创建进程的三行代码,是否仍会收到相同的错误? - DS_London
显示剩余15条评论
1个回答

0

有一些东西缺失:

  • STARTUPINFO初始化(感谢@CristiFati)
  • 带有C外部链接的xlAutoOpen入口点

这段代码可以编译(至少对我来说是这样),并在加载xll时显示记事本(我确实会收到一个缺少证书的安全警告,但这很可能是我的Excel设置被锁定了)。

//MyXll.cpp    
#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {     
        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));

        if( CreateProcess(TEXT("c:\\windows\\system32\\notepad.exe"), NULL, 
                  NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi) )
        {
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
        }
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C" __declspec(dllexport) int WINAPI xlAutoOpen(void)
{
    return 1;
}

我已经使用C运行时进行了静态链接(在代码生成下,选择“多线程调试”),并且具有_DEBUG_WINDOWSUNICODE_USRDLL预处理器定义。在高级属性中,“目标文件扩展名”设置为.xll。我没有使用预编译头文件。

使用MSVC Pro 22进行编译,并加载到Excel 16 64位中。

Excel将期望找到xlAutoOpen入口点,并且除非存在,否则不会识别xll。该函数不必执行任何操作(尽管在实际的xll中,这是函数注册发生的地方)。

如果您不提供任何Excel功能,则无需包含或链接任何Excel SDK元素(例如xlcall.hxlcall32.lib)。

文档链接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接