В настоящее время я пишу программу на C#, которая использует Spooler Api для печати PDF-документов. На самом деле он печатает стабильно, но проблема возникает, когда я хочу сделать это с разными настройками (ориентация, размер бумаги и т. д.). У него есть проблема: по-видимому, программа обходит драйверы принтера и отправляет документы с настройками по умолчанию. Мы используем принтер Konica Minolta 650i. Есть возможность складывания, но я понятия не имею, как к ней получить доступ. Поскольку мы вызываем очередь принтера как имя принтера, я подумал, что использования структуры DEVMODE и отправки ее в функцию SetPrinter будет достаточно. Итак, моя проблема в том, что я не могу понять, как заставить программу применять настройки из различных очередей печати.
Учитывая, что это проект моей работы, я обычно не делаю этого. У меня нет прав администратора. Хотя я однажды протестировал этот процесс, когда ИТ-команда предоставила мне их, но результат был тот же.
Что мне нужно сделать, чтобы получить доступ к настройкам очереди печати? Каковы реквизиты? Ниже приведен код, который я использую.
public enum PrintDocumentTemplateType
{
A3 = 1,
A4 = 2,
A5 = 3
}
public enum PrintDocumentOrientationType
{
Portrait = 1,
Landscape = 2
}
public class PrintingOptions
{
private readonly Dictionary
_templates
= new Dictionary()
{
{ PrintDocumentTemplateType.A3, "A3" },
{ PrintDocumentTemplateType.A4, "A4" },
{ PrintDocumentTemplateType.A5, "A5" },
};
public bool IsUserAdmin { get { return GetIsUserAdmin(); } }
///
/// Set to true if you want to use the printer's queue/driver
///
public bool AllowAdvancedSettings { get; set; } = true;
///
/// Set to true if you want ot change the settings of a printer with the properties here.
///
public bool ModifyPrinterSettings { get; set; } = false;
public PrintDocumentOrientationType Orientation { get; set; } = PrintDocumentOrientationType.Portrait;
public PrintDocumentTemplateType TemplateType { get; set; } = PrintDocumentTemplateType.A3;
public string TemplateTypeStr { get { return _templates[this.TemplateType]; } }
public bool FoldDocument { get; set; } = false;
private bool GetIsUserAdmin()
{
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
{
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
}
// Printer Invoke declarations
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool OpenPrinter(string printerName, out IntPtr hPrinter, IntPtr pDefault);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool OpenPrinter(string printerName, out IntPtr hPrinter, ref PRINTER_DEFAULTS pDefaults);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr pPrinterInfo, int Command);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool StartDocPrinter(IntPtr hPrinter, int level, [In] ref DOCINFO pDocInfo);
[DllImport("winspool.drv", SetLastError = true)]
private static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("winspool.drv", SetLastError = true)]
private static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("winspool.drv", SetLastError = true)]
private static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("winspool.drv", SetLastError = true)]
private static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, int dwCount, out int dwWritten);
[DllImport("winspool.drv", SetLastError = true)]
private static extern int DocumentProperties(IntPtr hWnd, IntPtr hPrinter, string pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetPrinter(IntPtr hPrinter, uint Level, IntPtr pPrinter, uint cbBuf, out uint pcbNeeded);
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int pcchBuffer);
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)]
static extern int SetPrinterData(IntPtr hPrinter, string pValueName, uint Type, IntPtr pData, uint cbData);
private const int PRINTER_CONTROL_SET = 2;
private const int DM_IN_BUFFER = 1;
private const int DM_OUT_BUFFER = 2;
// field selection in bits
private const int DM_ORIENTATION = 0x00000001;
private const int DM_PAPERSIZE = 0x00000002;
private const int DM_PAPERLENGTH = 0x00000004;
private const int DM_PAPERWIDTH = 0x00000008;
private const int DM_SCALE = 0x00000010;
private const int DM_POSITION = 0x00000020;
private const int DM_NUP = 0x00000040;
private const int DM_DISPLAYORIENTATION = 0x00000080;
private const int DM_COPIES = 0x00000100;
private const int DM_DEFAULTSOURCE = 0x00000200;
private const int DM_PRINTQUALITY = 0x00000400;
private const int DM_COLOR = 0x00000800;
private const int DM_DUPLEX = 0x00001000;
private const int DM_YRESOLUTION = 0x00002000;
private const int DM_TTOPTION = 0x00004000;
private const int DM_COLLATE = 0x00008000;
private const int DM_FORMNAME = 0x00010000;
private const int DM_LOGPIXELS = 0x00020000;
private const int DM_BITSPERPEL = 0x00040000;
private const int DM_PELSWIDTH = 0x00080000;
private const int DM_PELSHEIGHT = 0x00100000;
private const int DM_DISPLAYFLAGS = 0x00200000;
private const int DM_DISPLAYFREQUENCY = 0x00400000;
private const int DM_ICMMETHOD = 0x00800000;
private const int DM_ICMINTENT = 0x01000000;
private const int DM_MEDIATYPE = 0x02000000;
private const int DM_DITHERTYPE = 0x04000000;
private const int DM_PANNINGWIDTH = 0x08000000;
private const int DM_PANNINGHEIGHT = 0x10000000;
private const int DM_DISPLAYFIXEDOUTPUT = 0x20000000;
// values for DM_PAPERSIZE
private const short DMPAPER_A3 = 8;
private const short DMPAPER_A4 = 9;
private const short DMPAPER_A5 = 11;
// values for DM_ORIENTATION
private const short DMORIENT_PORTRAIT = 1;
private const short DMORIENT_LANDSCAPE = 2;
//const for security access
private const int PRINTER_ACCESS_ADMINISTER = 0x4;
private const int PRINTER_ACCESS_USE = 0x8;
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
private const int PRINTER_COMPLETE_ACCESS = (PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE | STANDARD_RIGHTS_REQUIRED);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct DOCINFO
{
[MarshalAs(UnmanagedType.LPTStr)]
public string pDocName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pOutputFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDataType;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct PRINTER_DEFAULTS
{
public IntPtr pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
private const int CCDEVICENAME = 32;
private const int CCFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)]
public string dmFormName;
public short dmUnusedPadding;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct PRINTER_INFO_2
{
[MarshalAs(UnmanagedType.LPTStr)]
public string pServerName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPrinterName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pShareName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPortName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDriverName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pComment;
[MarshalAs(UnmanagedType.LPTStr)]
public string pLocation;
public IntPtr pDevMode;
[MarshalAs(UnmanagedType.LPTStr)]
public string pSepFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pPrintProcessor;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDatatype;
[MarshalAs(UnmanagedType.LPTStr)]
public string pParameters;
public IntPtr pSecurityDescriptor;
public int Attributes;
public int Priority;
public int DefaultPriority;
public int StartTime;
public int UntilTime;
public int Status;
public int cJobs;
public int AveragePPM;
}
private static bool PrintFileWithWin32Api(string printerName, string filePath, PrintingOptions printingOptions)
{
uint pcbNeeded;
IntPtr pDevmode = IntPtr.Zero;
IntPtr pPrinter = IntPtr.Zero;
var pDefaults = new PRINTER_DEFAULTS()
{
//DesiredAccess = PRINTER_ACCESS_USE,
DesiredAccess = printingOptions.IsUserAdmin ? PRINTER_COMPLETE_ACCESS : PRINTER_ACCESS_USE,
pDatatype = IntPtr.Zero,
pDevMode = IntPtr.Zero
};
if (!OpenPrinter(printerName, out IntPtr hPrinter, ref pDefaults))
{
Console.WriteLine("Failed to open printer. Last win32 error: {0}", Marshal.GetLastWin32Error());
return false;
}
if (printingOptions.AllowAdvancedSettings)
{
// first call to DocumentProperties for setting up the size needed
int sizeNeeded = DocumentProperties(IntPtr.Zero, hPrinter, printerName, IntPtr.Zero, IntPtr.Zero, 0);
if (sizeNeeded 0)
{
IntPtr extraDataPointer = IntPtr.Add(pDevmode, devmode.dmSize);
byte[] extraData = new byte[devmode.dmDriverExtra];
Marshal.Copy(extraDataPointer, extraData, 0, devmode.dmDriverExtra);
}
#region Modifying DEVMODE
if (printingOptions.ModifyPrinterSettings)
{
// set bitflags
devmode.dmFields |= DM_PAPERSIZE | DM_ORIENTATION;
// set paper size
switch (printingOptions.TemplateType)
{
case PrintDocumentTemplateType.A3:
devmode.dmPaperSize = DMPAPER_A3;
break;
case PrintDocumentTemplateType.A4:
devmode.dmPaperSize = DMPAPER_A4;
break;
case PrintDocumentTemplateType.A5:
devmode.dmPaperSize = DMPAPER_A5;
break;
}
// set orientation
switch (printingOptions.Orientation)
{
case PrintDocumentOrientationType.Portrait:
devmode.dmOrientation = DMORIENT_PORTRAIT;
break;
case PrintDocumentOrientationType.Landscape:
devmode.dmOrientation = DMORIENT_LANDSCAPE;
break;
}
if (printingOptions.FoldDocument)
{
// TODO
}
// third call to modify the current devmode
if (DocumentProperties(IntPtr.Zero, hPrinter, printerName, pDevmode, pDevmode, DM_OUT_BUFFER | DM_IN_BUFFER) 0)
{
IntPtr unmanagedBytes = Marshal.AllocHGlobal(bytesRead);
Marshal.Copy(buffer, 0, unmanagedBytes, bytesRead);
if (!WritePrinter(hPrinter, unmanagedBytes, bytesRead, out int bytesWritten))
{
Console.WriteLine("Error writing to printer.");
return false;
}
Marshal.FreeHGlobal(unmanagedBytes);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error reading the file: " + ex.Message);
return false;
}
Marshal.FreeHGlobal(pDevmode);
Marshal.FreeHGlobal(pPrinter);
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
Console.WriteLine("File sent to printer successfully.");
return true;
}
public static void PrintFile()
{
string filePath = "pdfPath.pdf";
string printerName = "specificPrinterQueue";
var printerOptions = new PrintingOptions()
{
// setting which accesses the DEVMODE struct and sends it to Setprinter
AllowAdvancedSettings = true
};
bool successfulPrint = PrintFileWithWin32Api(filePath, printerName, printerOptions);
}
Я пробовал использовать Spire.PDF. Он применяет такие настройки, как ориентация и размер, но я не знаю, смогу ли я использовать его для более сложных настроек.
В настоящее время я пишу программу на C#, которая использует Spooler Api для печати PDF-документов. На самом деле он печатает стабильно, но проблема возникает, когда я хочу сделать это с разными настройками (ориентация, размер бумаги и т. д.). У него есть проблема: по-видимому, программа обходит драйверы принтера и отправляет документы с настройками по умолчанию. Мы используем принтер Konica Minolta 650i. Есть возможность складывания, но я понятия не имею, как к ней получить доступ. Поскольку мы вызываем очередь принтера как имя принтера, я подумал, что использования структуры DEVMODE и отправки ее в функцию SetPrinter будет достаточно. Итак, моя проблема в том, что я не могу понять, как заставить программу применять настройки из различных очередей печати. Учитывая, что это проект моей работы, я обычно не делаю этого. У меня нет прав администратора. Хотя я однажды протестировал этот процесс, когда ИТ-команда предоставила мне их, но результат был тот же. Что мне нужно сделать, чтобы получить доступ к настройкам очереди печати? Каковы реквизиты? Ниже приведен код, который я использую. [code]public enum PrintDocumentTemplateType { A3 = 1, A4 = 2, A5 = 3 }
public class PrintingOptions { private readonly Dictionary _templates = new Dictionary() { { PrintDocumentTemplateType.A3, "A3" }, { PrintDocumentTemplateType.A4, "A4" }, { PrintDocumentTemplateType.A5, "A5" }, };
public bool IsUserAdmin { get { return GetIsUserAdmin(); } } /// /// Set to true if you want to use the printer's queue/driver /// public bool AllowAdvancedSettings { get; set; } = true; /// /// Set to true if you want ot change the settings of a printer with the properties here. /// public bool ModifyPrinterSettings { get; set; } = false; public PrintDocumentOrientationType Orientation { get; set; } = PrintDocumentOrientationType.Portrait; public PrintDocumentTemplateType TemplateType { get; set; } = PrintDocumentTemplateType.A3; public string TemplateTypeStr { get { return _templates[this.TemplateType]; } } public bool FoldDocument { get; set; } = false; private bool GetIsUserAdmin() { using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) { WindowsPrincipal principal = new WindowsPrincipal(identity); return principal.IsInRole(WindowsBuiltInRole.Administrator); } } }
private const int DM_IN_BUFFER = 1; private const int DM_OUT_BUFFER = 2;
// field selection in bits private const int DM_ORIENTATION = 0x00000001; private const int DM_PAPERSIZE = 0x00000002; private const int DM_PAPERLENGTH = 0x00000004; private const int DM_PAPERWIDTH = 0x00000008; private const int DM_SCALE = 0x00000010; private const int DM_POSITION = 0x00000020; private const int DM_NUP = 0x00000040; private const int DM_DISPLAYORIENTATION = 0x00000080; private const int DM_COPIES = 0x00000100; private const int DM_DEFAULTSOURCE = 0x00000200; private const int DM_PRINTQUALITY = 0x00000400; private const int DM_COLOR = 0x00000800; private const int DM_DUPLEX = 0x00001000; private const int DM_YRESOLUTION = 0x00002000; private const int DM_TTOPTION = 0x00004000; private const int DM_COLLATE = 0x00008000; private const int DM_FORMNAME = 0x00010000; private const int DM_LOGPIXELS = 0x00020000; private const int DM_BITSPERPEL = 0x00040000; private const int DM_PELSWIDTH = 0x00080000; private const int DM_PELSHEIGHT = 0x00100000; private const int DM_DISPLAYFLAGS = 0x00200000; private const int DM_DISPLAYFREQUENCY = 0x00400000; private const int DM_ICMMETHOD = 0x00800000; private const int DM_ICMINTENT = 0x01000000; private const int DM_MEDIATYPE = 0x02000000; private const int DM_DITHERTYPE = 0x04000000; private const int DM_PANNINGWIDTH = 0x08000000; private const int DM_PANNINGHEIGHT = 0x10000000; private const int DM_DISPLAYFIXEDOUTPUT = 0x20000000;
// values for DM_PAPERSIZE private const short DMPAPER_A3 = 8; private const short DMPAPER_A4 = 9; private const short DMPAPER_A5 = 11;
// values for DM_ORIENTATION private const short DMORIENT_PORTRAIT = 1; private const short DMORIENT_LANDSCAPE = 2;
//const for security access private const int PRINTER_ACCESS_ADMINISTER = 0x4; private const int PRINTER_ACCESS_USE = 0x8; private const int STANDARD_RIGHTS_REQUIRED = 0xF0000; private const int PRINTER_COMPLETE_ACCESS = (PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE | STANDARD_RIGHTS_REQUIRED);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private struct DOCINFO { [MarshalAs(UnmanagedType.LPTStr)] public string pDocName; [MarshalAs(UnmanagedType.LPTStr)] public string pOutputFile; [MarshalAs(UnmanagedType.LPTStr)] public string pDataType; }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct PRINTER_DEFAULTS { public IntPtr pDatatype; public IntPtr pDevMode; public int DesiredAccess; }
[StructLayout(LayoutKind.Sequential)] public struct DEVMODE { private const int CCDEVICENAME = 32; private const int CCFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)] public string dmDeviceName; public short dmSpecVersion; public short dmDriverVersion; public short dmSize; public short dmDriverExtra; public int dmFields; public short dmOrientation; public short dmPaperSize; public short dmPaperLength; public short dmPaperWidth; public short dmScale; public short dmCopies; public short dmDefaultSource; public short dmPrintQuality; public short dmColor; public short dmDuplex; public short dmYResolution; public short dmTTOption; public short dmCollate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)] public string dmFormName; public short dmUnusedPadding; public short dmBitsPerPel; public int dmPelsWidth; public int dmPelsHeight; public int dmDisplayFlags; public int dmDisplayFrequency; }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct PRINTER_INFO_2 { [MarshalAs(UnmanagedType.LPTStr)] public string pServerName; [MarshalAs(UnmanagedType.LPTStr)] public string pPrinterName; [MarshalAs(UnmanagedType.LPTStr)] public string pShareName; [MarshalAs(UnmanagedType.LPTStr)] public string pPortName; [MarshalAs(UnmanagedType.LPTStr)] public string pDriverName; [MarshalAs(UnmanagedType.LPTStr)] public string pComment; [MarshalAs(UnmanagedType.LPTStr)] public string pLocation; public IntPtr pDevMode; [MarshalAs(UnmanagedType.LPTStr)] public string pSepFile; [MarshalAs(UnmanagedType.LPTStr)] public string pPrintProcessor; [MarshalAs(UnmanagedType.LPTStr)] public string pDatatype; [MarshalAs(UnmanagedType.LPTStr)] public string pParameters; public IntPtr pSecurityDescriptor; public int Attributes; public int Priority; public int DefaultPriority; public int StartTime; public int UntilTime; public int Status; public int cJobs; public int AveragePPM; }
if (!OpenPrinter(printerName, out IntPtr hPrinter, ref pDefaults)) { Console.WriteLine("Failed to open printer. Last win32 error: {0}", Marshal.GetLastWin32Error()); return false; }
if (printingOptions.AllowAdvancedSettings) { // first call to DocumentProperties for setting up the size needed int sizeNeeded = DocumentProperties(IntPtr.Zero, hPrinter, printerName, IntPtr.Zero, IntPtr.Zero, 0); if (sizeNeeded 0) { IntPtr extraDataPointer = IntPtr.Add(pDevmode, devmode.dmSize);
byte[] extraData = new byte[devmode.dmDriverExtra]; Marshal.Copy(extraDataPointer, extraData, 0, devmode.dmDriverExtra); }
#region Modifying DEVMODE if (printingOptions.ModifyPrinterSettings) { // set bitflags devmode.dmFields |= DM_PAPERSIZE | DM_ORIENTATION;
// set paper size switch (printingOptions.TemplateType) { case PrintDocumentTemplateType.A3: devmode.dmPaperSize = DMPAPER_A3; break; case PrintDocumentTemplateType.A4: devmode.dmPaperSize = DMPAPER_A4; break; case PrintDocumentTemplateType.A5: devmode.dmPaperSize = DMPAPER_A5; break; }
// set orientation switch (printingOptions.Orientation) { case PrintDocumentOrientationType.Portrait: devmode.dmOrientation = DMORIENT_PORTRAIT; break; case PrintDocumentOrientationType.Landscape: devmode.dmOrientation = DMORIENT_LANDSCAPE; break; }
if (printingOptions.FoldDocument) { // TODO }
// third call to modify the current devmode if (DocumentProperties(IntPtr.Zero, hPrinter, printerName, pDevmode, pDevmode, DM_OUT_BUFFER | DM_IN_BUFFER) 0) { IntPtr unmanagedBytes = Marshal.AllocHGlobal(bytesRead); Marshal.Copy(buffer, 0, unmanagedBytes, bytesRead);
if (!WritePrinter(hPrinter, unmanagedBytes, bytesRead, out int bytesWritten)) { Console.WriteLine("Error writing to printer."); return false; }
var printerOptions = new PrintingOptions() { // setting which accesses the DEVMODE struct and sends it to Setprinter AllowAdvancedSettings = true };
bool successfulPrint = PrintFileWithWin32Api(filePath, printerName, printerOptions); } [/code] Я пробовал использовать Spire.PDF. Он применяет такие настройки, как ориентация и размер, но я не знаю, смогу ли я использовать его для более сложных настроек.
У меня дома два компьютера, и я довольно часто переключаю рабочие станции с одного на другой. Еще есть ноутбук, которым я иногда пользуюсь и мне бы тоже хотелось, чтобы на нем была моя домашняя папка со всеми изменениями и настройками. Есть ли...
Я следовал учебным пособиям по печати и печати. Я использовал printpreviewcontrol вместо printpreviewdialog . Я также добавил кнопку «Свойства принтера» в свой диалог, поэтому я могу изменить настройки, такие как безграничные / серого, размер...
Я следовал учебным пособиям по печати и печати. Я использовал printpreviewcontrol вместо printpreviewdialog . Я также добавил кнопку «Свойства принтера» в свой диалог, поэтому я могу изменить настройки, такие как безграничные / серого, размер...
Я разрабатываю приложение, которое обеспечивает защиту от детей (блокировку непристойного содержимого, приложений и т. д.) в режиме киоска. И я хочу отключить сброс настроек. Я нашел решение, используя Samsung KNOX SDK (только для устройств...