Error: Cannot create ActiveX component calling legacy OBJ for COBOL

83 Views Asked by At

I have to import data from a web page to an accounting package running AcuCobol.

It is an IIS ASP .NET Core application.

In order to do this I have a VB program that does the actual import, since the error reporting seems better. I ran into issues which made me move the import into a stand alone application. The Web App now calls that, passing the file to be imported as an argument.

Everything runs fine on my development laptop (running Windows 10). But when I try to run it on the customer's server (running Windows Server 2016) The import standalone program fails with this error:

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

EDIT: Added more detailed Error produced:

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)).

Compounding the mystery is that if I run the stand alone program manually, it runs fine. It is only when I try to start the process from within IIS that I get this error.

Here are some code snippets, LMK if you need more.

The IIS code that executes the standalone:

        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;
        }

And here is the program code:

    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;
    }

If it matters, I am compiling the standalone program as .NET 4.5, AnyCPU, Prefer 32 Bit:

Application

Build Params

EDIT: Added VB Code, if it helps somehow...

    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
1

There are 1 best solutions below

1
samwu On

If this problem only occurs on iis, you can try this solution:

  1. Go to Website
  2. Select the application pool your 32-bit application will run under
  3. Click Advanced setting
  4. Set Enable 32-bit Applications to True