无法从托管wcf的windows服务启动WinWord

本文关键字:windows 服务 启动 WinWord wcf | 更新日期: 2023-09-27 18:16:59

我有这个WCF。当我从chrome浏览器(如http://localhost:8733/doc/run/Test.doc)调用它时,wcf-service返回:

Tect.doc Succeed

但是Word的窗口没有出现。我应该在代码中改变什么来打开Word的窗口?

namespace WordDavService
{
    [ServiceContract]
    public interface IWcfDocOpen
    {
        [WebGet(UriTemplate = "/run/{Path}", ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        string Run(string Path);
    }
    [AspNetCompatibilityRequirements(RequirementsMode =
        AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
    public class DocOpenWcfService : IWcfDocOpen
    {
        //public static void Main() 
        public string Run(string Path)
        {
            Task<string> thread = Task<string>.Factory.StartNew(() =>
               { return DocOpenWcfService.OpenWord(Path); });
            Task.WaitAll(thread);
            return Path+thread.Result;
        }
        protected static string OpenWord(string Path)
        {
            Word._Application application = null; ;
            Word._Document document = null; ;
            Object _Path = Path;
            try
            {
                application = new Word.Application();
                if (!string.IsNullOrEmpty(_Path.ToString()))
                    document = application.Documents.Open(ref _Path);
                application.Visible = true;
            }
            catch (Exception error)
            {
                try
                {
                    document.Close();
                }
                catch { }
                try
                {
                    application.Quit();
                }
                catch { }
                document = null;
                application = null;
                return error.Message+"innerExeption: "+error.InnerException.Message;
            }
            return "Succeed";
        }
    }
}

无法从托管wcf的windows服务启动WinWord

我不确定您指的是什么错误,但是您应该能够通过在尝试打开这些文件之前检查这些文件的存在来防止有关不可访问文件等的错误?自动化Word通常涉及许多像这样的防御性编程。

然而,我认为你有一个更大的问题。从Windows服务中自动使用Word是"不允许的",因为它不受微软的支持,而且可能违反许可条款。

这是可以做到的(很多人都这样做——就像我一样),但一般来说,人们会在一个没有登录用户的专用服务器上做这件事,而用户可能也在使用Office。在用户的个人电脑上做这件事会让我很紧张,因为你的服务和用户可能同时在运行Word。

如果您仍然想采用这种方法,如果您可以描述您所看到的特定错误或不稳定性,将会很有帮助。

请参阅这个答案,它可能会让你更进一步。

说明如何从windows服务启动gui进程。

这是我的认识:

namespace WordDavService
{
[ServiceContract]
public interface IWcfDocOpen
{
    [WebGet(UriTemplate = "/run/{Path}", ResponseFormat = WebMessageFormat.Json)]
    [OperationContract]
    string Run(string Path);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class DocOpenWcfService : IWcfDocOpen
{
    //public static void Main() 
    public string Run(string _Path)
    {
        int session = WinAPI.WTSGetActiveConsoleSessionId();
        if (session ==0xFFFFFFFF)
        {
            return "NoActiveSession";
        }
        IntPtr userToken;
        bool res = WinAPI.WTSQueryUserToken(session, out userToken);

        string path =  "C:''Windows''LauncherWord.exe";
        string dir = Path.GetDirectoryName(path);
       WinAPI.STARTUPINFO si = new WinAPI.STARTUPINFO();
        si.lpDesktop = "winsta0''default";
        si.cb = (uint)Marshal.SizeOf(si);
        WinAPI.PROCESS_INFORMATION pi = new WinAPI.PROCESS_INFORMATION();
        WinAPI.SECURITY_ATTRIBUTES sa = new WinAPI.SECURITY_ATTRIBUTES();
        sa.bInheritHandle = true;
        sa.length = Marshal.SizeOf(sa);
        sa.lpSecurityDescriptor = IntPtr.Zero;
        if (!WinAPI.CreateProcessAsUser(userToken,       // user token
                                        path+" "+_Path,           // exexutable path
                                        "",   // arguments
                                        ref sa,         // process security attributes ( none )
                                        ref sa,         // thread  security attributes ( none )
                                        true,          // inherit handles?
                                        0x02000000,              // creation flags
                                        IntPtr.Zero,    // environment variables
                                        dir,            // current directory of the new process
                                        ref si,         // startup info
                                        ref pi))        // receive process information in pi
        {
            int error = Marshal.GetLastWin32Error();
            return "Error CreateProcessAsUser:" + error + " File: " + path + " " + _Path;
        }
        else
            return "Success:" + path + " " + _Path;
    }
}
public static class WinAPI
{
    [DllImport("Kernel32.dll", SetLastError = true)]
    public static extern int WTSGetActiveConsoleSessionId();
   [DllImport("wtsapi32.dll", SetLastError = true)]
    public static extern bool WTSQueryUserToken(int Session,[Out] out IntPtr phToken);
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public uint dwProcessId;
        public uint dwThreadId;
    }
    public struct STARTUPINFO
    {
        public uint cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }
    public struct SECURITY_ATTRIBUTES
    {
        public int length;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
    }
  [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser",      SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern bool  CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, 
                      ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, 
                      bool bInheritHandle, Int32 dwCreationFlags, IntPtr lpEnvrionment,
                      string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, 
                      ref PROCESS_INFORMATION lpProcessInformation);
    }
}

此服务启动LauncherWord.exe,它像这样启动Word:

namespace LauncherWord
{
class Program
{
    static void Main(string[] args)
    {
        string Path = "";
        if (args.Length > 0)
            Path = args[0];
        OpenWord(Path);
    }
    protected static string OpenWord(string Path)
    {
        Word._Application application = null; ;
        Word._Document document = null; ;
        Object _Path = Path;
        try
        {
            application = new Word.Application();
            if (!string.IsNullOrEmpty(_Path.ToString()))
                document = application.Documents.Open(ref _Path,Type.Missing,(object)false);
            application.Visible = true;
        }
        catch (Exception error)
        {
            try
            {
                document.Close();
            }
            catch { }
            try
            {
                application.Quit();
            }
            catch { }
            document = null;
            application = null;
            return error.Message + "innerExeption: " + error.InnerException.Message;
        }
        return "Succed";
    }
  }
}

但是结果并不好,因为Word开始时会出现一些关于不可访问文件的错误。而Word的行为是不稳定的,它可能是不可接近的。

有没有人可以建议我如何使工作的过程与Word稳定?