Microsoft Word 互操作自动化 FilePrintSetup 错误

发布于 2025-01-01 16:59:31 字数 1572 浏览 1 评论 0 原文

我收到“打印机出现错误”。当在带有 Word 2010 的 Windows 7 上使用自动化将打印作业发送到打印机时。相同的代码在带有 Word 2007 的 Windows XP 盒子上运行良好。我不确定是 Windows 7 还是 Word 2010 导致了该错误。

感谢任何帮助,

using Microsoft.Office.Interop.Word;
.....

object oWordbasic = wordDoc.Application.WordBasic;

object[] argValues = new object[] { value, 1  }; //first arg is a printer name
String[] argNames = new String[] { "Printer", "DoNotSetAsSysDefault", };

//Error Here
oWordbasic.GetType().InvokeMember("FilePrintSetup", System.Reflection.BindingFlags.InvokeMethod, null, oWordbasic, argValues, null, null, argNames);

我收到以下错误

System.Reflection.TargetInvocationException was caught
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
       at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
       at PBP.ABC.Framework.Wrappers.Microsoft.Word.WordDocument.set_ActivePrinterName(String value) in 
  InnerException: System.Runtime.InteropServices.COMException
       HelpLink=wdmain11.chm#24696
       Message=There is a printer error.
       Source=Microsoft Word
       ErrorCode=-2146827168
       InnerException: 

如果我省略了打印机参数,则调用可以工作,但不会打印到指定的打印机。它将打印到默认打印机。

谢谢。

I am getting "There is a printer error." when tying to send a print job to a printer using automation on Windows 7 with Word 2010. Same code works fine on Windows XP box with Word 2007. I am not sure if Windows 7 or word 2010 is causing the error.

Any help appreciated

using Microsoft.Office.Interop.Word;
.....

object oWordbasic = wordDoc.Application.WordBasic;

object[] argValues = new object[] { value, 1  }; //first arg is a printer name
String[] argNames = new String[] { "Printer", "DoNotSetAsSysDefault", };

//Error Here
oWordbasic.GetType().InvokeMember("FilePrintSetup", System.Reflection.BindingFlags.InvokeMethod, null, oWordbasic, argValues, null, null, argNames);

I get the Error Below

System.Reflection.TargetInvocationException was caught
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
       at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
       at PBP.ABC.Framework.Wrappers.Microsoft.Word.WordDocument.set_ActivePrinterName(String value) in 
  InnerException: System.Runtime.InteropServices.COMException
       HelpLink=wdmain11.chm#24696
       Message=There is a printer error.
       Source=Microsoft Word
       ErrorCode=-2146827168
       InnerException: 

If I leave out the printer parameters, the invoke work but not printing to the printer specified. It will print to the default printer.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

尾戒 2025-01-08 16:59:31

可能对你有用 - 这是我在 Word 中必须执行的操作,才能在不更改活动打印机的情况下进行打印,我收到错误,发现有时 Word 只喜欢打印机名称,有时还想要端口。

...要获取打印机名称和端口,请使用 InstalledPrinter,如下所示

private InstalledPrinter PreferredPrinter { get; set; }
private InstalledPrinter DefaultPrinter { get; set; }

    private void SetDefaultAndPreferredPrinters()
    {
        if (UserSettings[SETTING_PREFERRED_PRINTER] == null)
        {
            UserSettings[SETTING_PREFERRED_PRINTER] = string.Empty;
        }
        _preferredPrinterName = ((string)UserSettings[SETTING_PREFERRED_PRINTER]).Trim();

        List<InstalledPrinter> installedPrinters = InstalledPrinter.GetList();

        DefaultPrinter = null;
        PreferredPrinter = null;

        foreach (InstalledPrinter installedPrinter in installedPrinters)
        {
            if (installedPrinter.IsDefault)
            {
                DefaultPrinter = installedPrinter;
            }
            if (installedPrinter.Name.Equals(_preferredPrinterName, StringComparison.InvariantCultureIgnoreCase))
            {
                PreferredPrinter = installedPrinter;
            }
        }
    }

public enum PrinterStatus{
  Other = 1,
  Unknown,
  Idle,
  Printing,
  Warmup,
  Stopped,
  Offline,
  Degraded
}

public class InstalledPrinter{

        private static readonly ILog _s_logger =
        LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

public string DriverName { get; set; }

public string Location { get; set; }

public string Name { get; set; }

public bool Network { get; set; }

public string PortName { get; set; }

public string ServerName { get; set; }

public bool Shared { get; set; }

public PrinterStatus Status { get; set; }

public bool WorkOffline { get; set; }

public bool IsDefault { get; set; }

public static List<InstalledPrinter> GetList()
{
    PrinterSettings ps = new PrinterSettings();
        string sDefault = ps.PrinterName;

    string query = "Select * From Win32_Printer";

    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);

    ManagementObjectCollection results = searcher.Get();

    List<InstalledPrinter> list = new List<InstalledPrinter>(results.Count);

    foreach (ManagementObject printManagementObject in results)
    {
        InstalledPrinter entry = new InstalledPrinter();

        foreach (PropertyInfo propertyInfo in typeof(InstalledPrinter).GetProperties()) {
            object[] oparams = {1};
            if (propertyInfo.Name != "IsDefault") {//The IsDefault property is worked out logically, the rest of the properties map identically to the columns of the WMI query results.
                try {
                    oparams[0] = ConvertValue(
                        printManagementObject[propertyInfo.Name], propertyInfo.PropertyType);
                    propertyInfo.GetSetMethod().Invoke(
                        entry,
                        oparams);
                }catch(Exception e) {
                    _s_logger.Error(string.Format("Failed to enumerate printer property Name:{0}, Type:{1}", propertyInfo.Name, propertyInfo.PropertyType));
                }
            }
        }
        _s_logger.Info(string.Format("Finished enumerating properties of printer: {0}", entry.Name == null ? "<Null>" : entry.Name));
        if (sDefault.Equals(entry.Name, StringComparison.CurrentCultureIgnoreCase)) {
            entry.IsDefault = true;
        }
        list.Add(entry);
    }
    return list;
}

private static object ConvertValue(object value, Type type)
{
    if (value != null)
    {
        object printerStatusRetval = null;
        if (type == typeof(DateTime))
        {
            string time = value.ToString();
            time = time.Substring(0, time.IndexOf("."));
            return DateTime.ParseExact(time, "yyyyMMddHHmmss", null);
        }
        else if (type == typeof(long))
            return Convert.ToInt64(value);
        else if (type == typeof(int))
            return Convert.ToInt32(value);
        else if (type == typeof(short))
            return Convert.ToInt16(value);
        else if (type == typeof(string))
            return value.ToString();
        else if (type == typeof(PrinterStatus))
            try {
                printerStatusRetval = Enum.Parse(typeof (PrinterStatus), value.ToString());
            } catch (Exception e) {
                _s_logger.Error(string.Format("Failed to convert PrinterStatus with value {0}", value));
                printerStatusRetval = value.ToString();
            }
                return printerStatusRetval;
    }
    return null;
}

}

...然后在实例化 Word 后,我有类似这样的内容来设置打印机:

            object[] oWordDialogParams = {PreferredPrinter.Name, true};
            object[] oWordDialogParamsWithPort = {string.Format("{0} on {1}", PreferredPrinter.Name, PreferredPrinter.PortName), true};
            string[] argNames = {"Printer", "DoNotSetAsSysDefault"};
//oWord is my own class that provides a fairly simple wrapper around MS Word
            oWord.Application.ActivePrinter = UserSettings[SETTING_PREFERRED_PRINTER] as string;
            Dialog printDialog = oWord.Application.Dialogs[WdWordDialog.wdDialogFilePrintSetup];
            object wordBasic = oWord.Application.WordBasic;
            try {
                wordBasic.GetType().InvokeMember("FilePrintSetup"
                    , BindingFlags.InvokeMethod
                    , null
                    , wordBasic
                    , oWordDialogParams
                    , null
                    , null
                    , argNames);
            }catch(Exception e) {
                _s_logger.Info("Failed to print using printer name, trying printer name and port", e);
                try {
                    wordBasic.GetType().InvokeMember("FilePrintSetup"
                        , BindingFlags.InvokeMethod
                        , null
                        , wordBasic
                        , oWordDialogParamsWithPort
                        , null
                        , null
                        , argNames);
                }catch(Exception e2) {
                    _s_logger.Info("Failed to print using printer name and port", e2);
                    throw;
                }
            }

Might work for you - this is what I had to do in Word to print without changing the active printer, I was getting an error and found that sometimes Word liked just the printer name and other times wanted to also have the port.

... to get the printer names and ports use InstalledPrinter as below

private InstalledPrinter PreferredPrinter { get; set; }
private InstalledPrinter DefaultPrinter { get; set; }

    private void SetDefaultAndPreferredPrinters()
    {
        if (UserSettings[SETTING_PREFERRED_PRINTER] == null)
        {
            UserSettings[SETTING_PREFERRED_PRINTER] = string.Empty;
        }
        _preferredPrinterName = ((string)UserSettings[SETTING_PREFERRED_PRINTER]).Trim();

        List<InstalledPrinter> installedPrinters = InstalledPrinter.GetList();

        DefaultPrinter = null;
        PreferredPrinter = null;

        foreach (InstalledPrinter installedPrinter in installedPrinters)
        {
            if (installedPrinter.IsDefault)
            {
                DefaultPrinter = installedPrinter;
            }
            if (installedPrinter.Name.Equals(_preferredPrinterName, StringComparison.InvariantCultureIgnoreCase))
            {
                PreferredPrinter = installedPrinter;
            }
        }
    }

public enum PrinterStatus{
  Other = 1,
  Unknown,
  Idle,
  Printing,
  Warmup,
  Stopped,
  Offline,
  Degraded
}

public class InstalledPrinter{

        private static readonly ILog _s_logger =
        LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

public string DriverName { get; set; }

public string Location { get; set; }

public string Name { get; set; }

public bool Network { get; set; }

public string PortName { get; set; }

public string ServerName { get; set; }

public bool Shared { get; set; }

public PrinterStatus Status { get; set; }

public bool WorkOffline { get; set; }

public bool IsDefault { get; set; }

public static List<InstalledPrinter> GetList()
{
    PrinterSettings ps = new PrinterSettings();
        string sDefault = ps.PrinterName;

    string query = "Select * From Win32_Printer";

    ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);

    ManagementObjectCollection results = searcher.Get();

    List<InstalledPrinter> list = new List<InstalledPrinter>(results.Count);

    foreach (ManagementObject printManagementObject in results)
    {
        InstalledPrinter entry = new InstalledPrinter();

        foreach (PropertyInfo propertyInfo in typeof(InstalledPrinter).GetProperties()) {
            object[] oparams = {1};
            if (propertyInfo.Name != "IsDefault") {//The IsDefault property is worked out logically, the rest of the properties map identically to the columns of the WMI query results.
                try {
                    oparams[0] = ConvertValue(
                        printManagementObject[propertyInfo.Name], propertyInfo.PropertyType);
                    propertyInfo.GetSetMethod().Invoke(
                        entry,
                        oparams);
                }catch(Exception e) {
                    _s_logger.Error(string.Format("Failed to enumerate printer property Name:{0}, Type:{1}", propertyInfo.Name, propertyInfo.PropertyType));
                }
            }
        }
        _s_logger.Info(string.Format("Finished enumerating properties of printer: {0}", entry.Name == null ? "<Null>" : entry.Name));
        if (sDefault.Equals(entry.Name, StringComparison.CurrentCultureIgnoreCase)) {
            entry.IsDefault = true;
        }
        list.Add(entry);
    }
    return list;
}

private static object ConvertValue(object value, Type type)
{
    if (value != null)
    {
        object printerStatusRetval = null;
        if (type == typeof(DateTime))
        {
            string time = value.ToString();
            time = time.Substring(0, time.IndexOf("."));
            return DateTime.ParseExact(time, "yyyyMMddHHmmss", null);
        }
        else if (type == typeof(long))
            return Convert.ToInt64(value);
        else if (type == typeof(int))
            return Convert.ToInt32(value);
        else if (type == typeof(short))
            return Convert.ToInt16(value);
        else if (type == typeof(string))
            return value.ToString();
        else if (type == typeof(PrinterStatus))
            try {
                printerStatusRetval = Enum.Parse(typeof (PrinterStatus), value.ToString());
            } catch (Exception e) {
                _s_logger.Error(string.Format("Failed to convert PrinterStatus with value {0}", value));
                printerStatusRetval = value.ToString();
            }
                return printerStatusRetval;
    }
    return null;
}

}

...then after instantiating Word I have something like this to set the printer:

            object[] oWordDialogParams = {PreferredPrinter.Name, true};
            object[] oWordDialogParamsWithPort = {string.Format("{0} on {1}", PreferredPrinter.Name, PreferredPrinter.PortName), true};
            string[] argNames = {"Printer", "DoNotSetAsSysDefault"};
//oWord is my own class that provides a fairly simple wrapper around MS Word
            oWord.Application.ActivePrinter = UserSettings[SETTING_PREFERRED_PRINTER] as string;
            Dialog printDialog = oWord.Application.Dialogs[WdWordDialog.wdDialogFilePrintSetup];
            object wordBasic = oWord.Application.WordBasic;
            try {
                wordBasic.GetType().InvokeMember("FilePrintSetup"
                    , BindingFlags.InvokeMethod
                    , null
                    , wordBasic
                    , oWordDialogParams
                    , null
                    , null
                    , argNames);
            }catch(Exception e) {
                _s_logger.Info("Failed to print using printer name, trying printer name and port", e);
                try {
                    wordBasic.GetType().InvokeMember("FilePrintSetup"
                        , BindingFlags.InvokeMethod
                        , null
                        , wordBasic
                        , oWordDialogParamsWithPort
                        , null
                        , null
                        , argNames);
                }catch(Exception e2) {
                    _s_logger.Info("Failed to print using printer name and port", e2);
                    throw;
                }
            }
无言温柔 2025-01-08 16:59:31

没有找到解决问题的方法。放入 if 条件以不同方式处理 Word 2010 并使用非托管代码进行打印。 链接 概述了如何执行此操作

Did not find a way to fix the issue. Put in a if condition to handle Word 2010 differently and use unmanaged code to print. Link outlines how to do this

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文