none
Unable to execute excel macros by excel interop calls from process created by an impersonated user RRS feed

  • Question

  • Hello,

    I have a huge application that can also execute excel macros (by interop excel calls) which works just fine when executed manually by some user. I also have a local service running on a server where the application is installed with a purpose of scheduling executions of the main application and because the service is running under service credentials I make a few calls to log in a user, set impersonation mode and environment variables and execute the process (of main applicaiton) under the desired domain user account.

    Everything works fine at my side but when i send it to customer he gets the following error when the app is about to run the macros:

    "The macro may not be available in this workbook or all macros may be disabled"

    I have searched the internet for 3 days now and none of the solutions about this error message were helpful - i have the path of the xlsm file qualified by apostrophes, the customer sent a screenshot confirming that the excel trust center settings enable all macros and trust the VB object model and also when he executes the macro from app that was started by him manually he does not get this error message.

    Here is the code that starts the main app from the service:

    	// login user
    	result = LogonUser(username, domain, password, 
    		(int)Executer.LOGON_TYPE.LOGON32_LOGON_NETWORK_CLEARTEXT, 
    		(int)Executer.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out token);
    
    	// security
    	SECURITY_ATTRIBUTES processAttributes = new SECURITY_ATTRIBUTES();
    
    	SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();
    	IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd));
    	Marshal.StructureToPtr(sd, ptr, false);
    	InitializeSecurityDescriptor(ptr, SECURITY_DESCRIPTOR_REVISION);
    	sd = (SECURITY_DESCRIPTOR)Marshal.PtrToStructure(ptr, typeof(SECURITY_DESCRIPTOR));
    
    	result = SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false);
    
    	//create token
    	primaryToken = new IntPtr();
    	result = DuplicateTokenEx(token, 0, ref processAttributes, 
    		SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
    		TOKEN_TYPE.TokenPrimary, out primaryToken);
    
    	processAttributes.SecurityDescriptor = ptr;
    	processAttributes.Length = (uint)Marshal.SizeOf(sd);
    	processAttributes.InheritHandle = true;
    
    	Executer.SECURITY_ATTRIBUTES threadAttributes = new Executer.SECURITY_ATTRIBUTES();
    	threadAttributes.SecurityDescriptor = IntPtr.Zero;
    	threadAttributes.Length = 0;
    	threadAttributes.InheritHandle = false;
    
    	bool inheritHandles = true;
    
    	// Create environment
    	CreationFlags creationFlags = CreationFlags.CREATE_UNICODE_ENVIRONMENT | CreationFlags.CREATE_NEW_CONSOLE;
    	bool createdEnvBlock = CreateEnvironmentBlock(out environment, token, false);
    
    	// load user profile
    	profileInfo = new ProfileInfo();
    	profileInfo.dwSize = Marshal.SizeOf(profileInfo);
    	profileInfo.lpUserName = username;
    	profileInfo.dwFlags = 1;
    	loadSuccess = LoadUserProfile(token, ref profileInfo);
    
    	// create process
    	Executer.STARTUPINFO startupInfo = new Executer.STARTUPINFO();
    	startupInfo.Desktop = "";
    
    	Executer.PROCESS_INFORMATION pi;
    	result = CreateProcessAsUser(
    		primaryToken, applicationName, commandLine, ref processAttributes,
    		ref threadAttributes, inheritHandles, (uint)creationFlags, environment, currDirectory,
    		ref startupInfo, out pi);
    
    	WaitForSingleObject(pi.Process, INFINITE);
    


    And from within the main app i call something like this:

    	
    	Type type_Excel = excelPIA.GetType("Microsoft.Office.Interop.Excel.ApplicationClass");
    	
    	// < bunch of code to start excel and open my xlsm file >
    	
    	string macroFullName = string.Format("'{0}'!{1}", tempFileName, macro);
    	// and here is the error
    	type_Excel.InvokeMember("Run", BindingFlags.InvokeMethod, null, target, new object[] { macroFullName })
    	

    Any idea on why it works at my side and does not on customer side when executed from the service using the "create process" approach? I have local admin rights on my account so i also tried to create a new local user without admin privileges and i still can execute the macros without any problem. I then asked the user to enable Trust center logging and send me the log afterwards but the log was blank after execution.

    Is there something that i can check with account privileges or ask the user for some specific information? I already ran out of ideas.

    Thanks,

    Martin

    • Moved by 宝宝徐 Wednesday, May 31, 2017 1:44 AM
    Thursday, May 18, 2017 11:03 AM

Answers

  • Hi Martin,

    Thank you for posting in MSDN forum.

    Please see:

    https://support.microsoft.com/en-sg/help/257757/considerations-for-server-side-automation-of-office

    Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.

    Best Regards,


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, May 26, 2017 3:21 AM