由于来自微软的最新安全更新已使Jet OLEDB Provider无法使用,我必须重写几个较旧的VBScripts。
是否有更好的方法在Windows Server 2008 R2和2012 R2上安装打印机表单,然后通过regsvr32 / COM / VBscript调用过时的prnadmin.dll
?
prnadmin.dll
最初是在Windows Server 2000资源工具包中引入的,我想将整个脚本迁移到PowerShell。
很遗憾,我在模块PrintManagement
中找不到任何有用的PowerShell cmdlet。那么如何使用PSH将自定义表单添加到打印机服务器?
答案 0 :(得分:1)
添加系统表单定义的编程方法是调用AddForm
。我知道这个调用没有一个好的包装器,但P /调用AddForm
有效。我写了一个快速包装器和posted it on GitHub。
使用包装器的示例:
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.
PS C:\Drop> Import-Module .\PowershellPrinterFormsModule.dll
PS C:\Drop> Add-SystemForm -Name 'Demo User Form try 1' -Units Inches -Size '4,5'
PS C:\Drop> Add-SystemForm -Name 'Demo User Form try 2' -Units Inches -Size '4,5' -Margin '0.25,0.5'
PS C:\Drop> Add-SystemForm -Name 'Demo User Form try 3' -Units Millimeters -Size '80,50' -Margin '10,10,0,0'
实际P / Invoke对AddForm
的调用:
SafePrinterHandle hServer;
if (!OpenPrinter(null, out hServer, IntPtr.Zero))
{
throw new Win32Exception();
}
using (hServer)
{
var form = new FORM_INFO_1()
{
Flags = 0,
Name = this.Name,
Size = (SIZEL)pageSize,
ImageableArea = (RECTL)imageableArea
};
if (!AddForm(hServer, 1, ref form))
{
throw new Win32Exception();
}
}
internal static class NativeMethods
{
#region Constants
internal const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
#endregion
#region winspool.drv
private const string Winspool = "winspool.drv";
[DllImport(Winspool, SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool OpenPrinter(string szPrinter, out SafePrinterHandle hPrinter, IntPtr pd);
public static SafePrinterHandle OpenPrinter(string szPrinter)
{
SafePrinterHandle hServer;
if (!OpenPrinter(null, out hServer, IntPtr.Zero))
{
throw new Win32Exception();
}
return hServer;
}
[DllImport(Winspool, SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport(Winspool, SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool EnumForms(SafePrinterHandle hPrinter, int level, IntPtr pBuf, int cbBuf, out int pcbNeeded, out int pcReturned);
[DllImport(Winspool, SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool AddForm(SafePrinterHandle hPrinter, int level, [In] ref FORM_INFO_1 form);
[DllImport(Winspool, SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool DeleteForm(SafePrinterHandle hPrinter, string formName);
#endregion
#region Structs
[StructLayout(LayoutKind.Sequential)]
internal struct FORM_INFO_1
{
public int Flags;
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
public SIZEL Size;
public RECTL ImageableArea;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SIZEL
{
public int cx;
public int cy;
public static explicit operator SIZEL(Size r)
=> new SIZEL { cx = (int)r.Width, cy = (int)r.Height };
public static explicit operator Size(SIZEL r)
=> new Size(r.cx, r.cy);
}
[StructLayout(LayoutKind.Sequential)]
internal struct RECTL
{
public int left;
public int top;
public int right;
public int bottom;
public static explicit operator RECTL(Rect r)
=> new RECTL { left = (int)r.Left, top = (int)r.Top, right = (int)r.Right, bottom = (int)r.Bottom };
public static explicit operator Rect(RECTL r)
=> new Rect(new Point(r.left, r.top), new Point(r.right, r.bottom));
}
#endregion
}
internal sealed class SafePrinterHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafePrinterHandle()
: base(true)
{
}
protected override bool ReleaseHandle()
{
return NativeMethods.ClosePrinter(handle);
}
}