Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WinSpool OpenPrinter访问被拒绝_C#_Asp.net_Vb.net_Winapi_Printing - Fatal编程技术网

C# WinSpool OpenPrinter访问被拒绝

C# WinSpool OpenPrinter访问被拒绝,c#,asp.net,vb.net,winapi,printing,C#,Asp.net,Vb.net,Winapi,Printing,这是第335次有人问这个问题,但我没有找到答案。 我正试图从ASP.net C#应用程序通过WinSpool api将原始数据直接发送到打印机 我的代码只是一个副本 这里有错误 if( OpenPrinter( szPrinterName.Normalize(), out hPrinter, IntPtr.Zero ) ) 它适用于本地打印机,但对于共享网络打印机,OpenPrinter(实际上是GetLastError的结果)的结果总是5-访问被拒绝 我试过了 打印机的不同值\u默认值,具

这是第335次有人问这个问题,但我没有找到答案。 我正试图从ASP.net C#应用程序通过WinSpool api将原始数据直接发送到打印机

我的代码只是一个副本

这里有错误

if( OpenPrinter( szPrinterName.Normalize(), out hPrinter, IntPtr.Zero ) )
它适用于本地打印机,但对于共享网络打印机,
OpenPrinter
(实际上是
GetLastError
的结果)的结果总是
5-访问被拒绝

我试过了

  • 打印机的不同值\u默认值
    ,具有不同的
    期望访问组合
  • 向用户授予管理员权限
  • 安装打印机
我必须注意,我只是想打印,而不是更改打印机配置或需要管理权限的内容

我可以使用打印机选项页和嵌入其中的测试工具从服务器打印到此共享打印机。所以打印机可以工作。如何通过API访问it


更新:如果从Windows应用程序或控制台应用程序调用,则此代码看起来工作正常。那么为什么在Web应用程序中拒绝访问


更新2:问题可能是因为打印机安装在主机PC上并与虚拟PC共享(或在生产中:打印机安装在域内并与DMZ中的PC共享),并且没有适当的方法将此打印机的权限授予虚拟PC的用户(或域外的用户)



更新3:这里还有一个事实。如果我从virtual in explorer浏览到主机PC(如下图所示),我会收到通知,输入用户名和密码以访问主机PC。如果在这之后我选中“保存密码”,整个“访问被拒绝”问题将消失,直到我更改主机PC上的密码为止。

默认情况下,在IIS下运行的ASP.Net网站在低权限本地用户帐户下运行。为了允许客户端从网站访问域资源,您需要将运行IIS的用户(称为应用程序池标识)更改为对所有内容(网络打印机和IIS本身)都具有正确权限的域用户

最简单的解决方案(可能有更安全的)是将IIS应用池更改为使用内置的NetworkService帐户。此帐户会自动添加到您的域中,名为MyDomain\MyHostName$,因此您可以使用此帐户授予打印机权限(或其他所需的权限)

要更改应用程序池标识,只需打开IIS管理器,选择正确的应用程序池,然后点击“高级设置”,并查找设置“标识”

更多信息请点击此处:

添加我的答案,因为接受的答案无法解决我的问题,对于任何可能出现此错误的人,如果:

  • 生成任何CPU或x64时会出现错误
  • 构建x86时不会出现错误
问题似乎在于GC回收打印机的默认结构,然后OpenPrinter尝试写入该位置。建议的解决方案是使用保留在堆栈上的类

public class PrinterSettings
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal class PRINTERDEFAULTSClass
    {
        public IntPtr pDatatype;
        public IntPtr pDevMode;
        public int DesiredAccess;
    } 

    [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    private static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, PRINTERDEFAULTSClass pdc);

    public DEVMODE GetPrinterSettings(string PrinterName)
    {
        DEVMODE dm;

        var pdc = new PRINTERDEFAULTSClass
        {
            pDatatype = new IntPtr(0),
            pDevMode = new IntPtr(0),
            DesiredAccess = PRINTER_ALL_ACCESS
        };

        var nRet = Convert.ToInt32(OpenPrinter(PrinterName,
                out hPrinter, pdc));
    }
}

你似乎已经回答了你自己的问题。它不起作用,因为尝试打印的用户没有打印权限。您在授予权限时遇到问题,因为用户不在域中,但打印机在域中。还剩下什么?应用程序池使用什么标识?你说的“给用户管理员权限”是指哪个用户?我的错。我忘了说我已经尝试将应用程序池标识更改为我自己。在我的帐户下,我可以从控制台打印,但不能从web应用程序打印。这两种管理员权限都不起作用。@arx的问题不在于授予权限,而在于对同一用户帐户的控制台应用程序有效,而对web应用程序无效。我相信它与GUI有某种联系。因为web应用程序没有使用它,所以操作系统会以不同的方式对待它的安全性。您能否确认您正在完全信任而不是部分信任下运行IIS?我已尝试更改标识。没有效果。但我认为我应该尝试使用NetworkService帐户,因为它默认存在于任何机器上。感谢您的提示。如果您通过Windows任务计划程序将控制台应用程序设置为与NetworkService帐户一起运行,则可能有助于您进行调试。如果同一帐户上的同一代码在使用NetworkService的任务下正常工作,但在使用NetworkService的IIS下失败,则可以排除权限问题,并关注IIS config.Hi。。我也面临同样的问题。并想尝试您的解决方案,但对您的代码有一些问题。。你能解释一下DEVMODE类型是什么意思,如果是外部的,在哪里/如何导入它吗?
DEVMODE
RawPrinterHelper
类使用的结构,你可以找到它的许多实现,例如。