IIS调用独立程序创建AcuGT ActiveX组件时遇权限拒绝错误
问题:IIS调用独立程序创建ActiveX组件时触发权限拒绝错误
我需要将网页数据导入运行AcuCobol的会计软件,采用IIS托管的ASP.NET Core应用,通过调用独立VB程序完成导入。该程序在本地Windows 10环境运行正常,但在客户的Windows Server 2016服务器上,手动运行独立程序无问题,仅当由IIS启动进程调用时会报错。
错误信息
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中调用独立程序的代码
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("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; }
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
编译参数
独立程序编译参数为:.NET 4.5、AnyCPU、优先32位模式。
解决方案
- 配置COM组件权限
- 运行
dcomcnfg打开组件服务,找到CLSID为{BFBBB600-C4DB-11D2-B11B-74F606C10000}对应的AcuGT.Application组件(可通过注册表搜索CLSID定位)。 - 右键组件选择
属性->安全,确保IIS应用池运行账户(默认ApplicationPoolIdentity或自定义账户)拥有启动和激活权限、访问权限的允许权限。
- 运行
- 调整IIS应用池身份
将应用池身份改为具有足够权限的账户:比如LocalSystem(权限高,需评估安全风险),或专门创建的服务账户,该账户需能访问AcuCobol安装目录、导入文件目录、临时目录及日志目录。 - 验证DCOM系统级权限
在组件服务中进入计算机->我的电脑->属性->COM安全,编辑启动和激活权限的限制列表,确保IIS运行账户被允许本地启动和激活。 - 检查文件系统权限
给IIS应用池账户添加以下目录的读写权限:- 独立程序所在目录
- 配置中的临时目录(
smTempDirectory、swTempDirectory) - AcuCobol安装目录及配置文件路径
- 日志输出目录
- 确认32位COM组件注册
由于程序优先32位模式,在64位Windows Server 2016上,需使用C:\Windows\SysWOW64\regsvr32.exe注册AcuGT对应的32位DLL文件。
内容的提问来源于stack exchange,提问作者MarkJoel60
相关产品推荐
相关产品推荐

