错误:无法为 COBOL 创建调用旧版 OBJ 的 ActiveX 组件

Error: Cannot create ActiveX component calling legacy OBJ for COBOL

提问人:MarkJoel60 提问时间:11/3/2023 最后编辑:MarkJoel60 更新时间:11/10/2023 访问量:60

问:

我必须将数据从网页导入到运行 AcuCobol 的会计包中。

它是一个 IIS ASP .NET Core 应用程序。

为了做到这一点,我有一个VB程序来执行实际的导入,因为错误报告似乎更好。我遇到了一些问题,这使我将导入移动到独立应用程序中。Web 应用现在调用该函数,并将要导入的文件作为参数传递。

在我的开发笔记本电脑(运行 Windows 10)上一切正常。但是当我尝试在客户的服务器(运行 Windows Server 2016)上运行它时,导入独立程序失败并出现以下错误:

Exit code 255
Unhandled Exception: System.Exception: Cannot create ActiveX component.
   at Microsoft.VisualBasic.Interaction.CreateObject(String ProgId, String ServerName)
   at SW.SWImporter.SWImporter.Import(String fullSWPath, String companyName, String importFormatName, String fullSWImportDirectory, String filename, String fullLogfilePathAndName, String SWConfig) in D:\bbrepo\BZJT\Importer\SW\SWImporter.vb:line 29
   at RunImportmate.ImportmateProgram.callSWImporter(String fullImportFileName, String importFormatName) in D:\ASG\repo\Importer\RunImportmate\Program.cs:line 75
   at RunImportmate.ImportmateProgram.Main(String[] args) in D:\ASG\repo\Importer\RunImportmate\Program.cs:line 37

编辑:添加了更详细的错误产生:

2023-11-07 20:54:57 - ERROR: Retrieving the COM class factory for component with 
CLSID {BFBBB600-C4DB-11D2-B11B-74F606C10000} failed 
due to the following error: 80070005 Access is denied. 
(Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).

更复杂的是,如果我手动运行独立程序,它运行良好。只有当我尝试从 IIS 中启动该过程时,才会收到此错误。

这里有一些代码片段,如果你需要更多,可以参考 LMK。

执行独立 IIS 代码:

        try
        {
            string ForwardSlash = @"/";
            string BackSlash = @"\";

            var ImportmateDirectory = Program.Configuration["SWIMP:ImportmateDirectory"];
            var executablePath = ImportmateDirectory + "/RunImportmate.exe";
            // Good ol' DOS commands won't accept a /
            executablePath = executablePath.Replace(ForwardSlash, BackSlash);
            ImportmateDirectory = ImportmateDirectory.Replace(ForwardSlash, BackSlash);
            var processStartInfo = new ProcessStartInfo
            {
                FileName = executablePath,
                Arguments = $"\"{filePath}\"",
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true,
                WorkingDirectory = ImportmateDirectory // Set the working directory
            };
            var args = processStartInfo.Arguments;
            using var process = new Process
            {
                StartInfo = processStartInfo
            };

            process.Start();

            // Read standard output and error if needed
            string output = await process.StandardOutput.ReadToEndAsync();
            string error = await process.StandardError.ReadToEndAsync();

            process.WaitForExit();
            int exitCode = process.ExitCode;
            return exitCode;
        }

这是程序代码:

    static void Main(string[] args)
    {
        String FileToImport = args[0];
        String importFormatName = System.Configuration.ConfigurationManager.AppSettings["importFormatName"];
        String smallNameDirectory = System.Configuration.ConfigurationManager.AppSettings["smTempDirectory"];
        string smFileToImport = "tmpImp.txt";
        File.Copy(FileToImport, smFileToImport, true);  // copy and delete old file
        writeLOGFile(            writeLOGFile("Renaming " + FileToImport + " To: " + smFileToImport + " to avoid long name issues ");
        String result = callSWImporter(smFileToImport, importFormatName);
        if (result.ToUpper() == "OK")
        {
            Console.WriteLine("SWImport was successful");
        }
        else
        {
            Console.Error.WriteLine("ERROR: SWImport was NOT successful for File: "
                + FileToImport + "(See LogFile)");
        }
    }           // main end brace
    static public string callSWImporter(String fullImportFileName, String importFormatName)
    {
        String fullSWPath = System.Configuration.ConfigurationManager.AppSettings["fullSWPath"];
        String companyName = System.Configuration.ConfigurationManager.AppSettings["companyName"];
        String swTempDirectory = System.Configuration.ConfigurationManager.AppSettings["swTempDirectory"];
        String importLogPathAndName = System.Configuration.ConfigurationManager.AppSettings["importLogPathAndName"];
        String SWConfig = System.Configuration.ConfigurationManager.AppSettings["SWConfig"];

        // Call SouthWare AcuGT to import the file
        FileInfo ImportFileNameInfo = new FileInfo(fullImportFileName);
        String importFileName = ImportFileNameInfo.Name;

        SWImporter swImporter = new SWImporter();  // This is a VB.NET class
        if (swImporter != null)
        {
            Console.WriteLine("Create swImporter from SW Object: SUCCESS!");
        }
        String result = swImporter.Import(fullSWPath,
                                            companyName,
                                            importFormatName,
                                            swTempDirectory ,
                                            importFileName,
                                            importLogPathAndName,
                                            SWConfig);
        Console.WriteLine("swImporter.Import COMPLETE. Result = " + result);
        return result;
    }

如果重要的话,我将独立程序编译为 .NET 4.5、AnyCPU、首选 32 位:

Application

Build Params

编辑:添加了VB代码,如果它以某种方式有帮助...

    Public Function Import(ByVal fullSWPath As String, ByVal companyName As String, ByVal importFormatName As String, ByVal fullSWImportDirectory As String,
                           ByVal filename As String, ByVal fullLogfilePathAndName As String, SWConfig As String) As String

        Dim configFile ' ACUCOBOL-GT config file
        Dim AcuGT1 ' ACUCOBOL-GT ActiveX control
        Dim retVal ' Return value
        Dim chkVal ' Check Paramerter values
        Dim imStatus As String ' ImportMate Status
        Dim newKey ' New key if new record
        Dim acug1 As Object
        Dim cstType

        configFile = fullSWPath & SWConfig
        AcuGT1 = CreateObject("AcuGT.Application")
        AcuGT1.Initialize("-c " & configFile & " -le " & fullLogfilePathAndName)  'this is to create a log file

        retVal = AcuGT1.Call("I2OPNCOM.OBJ", companyName, importFormatName, fullSWImportDirectory, filename, filename, "", "", imStatus, newKey)

        AcuGT1.Shutdown()
        Import = imStatus
    End Function
C# vb.net IIS ActiveX

评论

0赞 HardCode 11/3/2023
VB代码在哪里?
0赞 MarkJoel60 11/4/2023
VB 代码非常特定于 AcuCobol 对象的调用方式......所以不确定它有什么帮助。但是我已经编辑了我的问题。
0赞 Hans Passant 11/5/2023
这种古老的 VB6 样式错误报告非常无用。让它变得更好,而不是 CreateObject() 使用 Activator.CreateInstance(Type.GetTypeFromProgID(“yadayada”))
0赞 MarkJoel60 11/9/2023
@HansPassant - 更新了更详细的错误。(我认为这是Microsoft Server 2016根本不允许的问题....?

答:

0赞 samwu 11/10/2023 #1

如果此问题仅发生在 iis 上,您可以尝试以下解决方案:

  1. 访问网站
  2. 选择 32 位应用程序将在其下运行的应用程序池
  3. 点击高级设置
  4. 将“启用 32 位应用程序”设置为“True”

评论

0赞 MarkJoel60 11/16/2023
我不得不转向不同的解决方案(我创建了一个后台服务来监视要创建的导入文件,并通过它调用组件,这似乎满足了要求。但我很好奇这是否会奏效......如果我能找到一种方法来测试它,我会并报告。