当我目前正在尝试部署一个简单的应用程序用作小型办公室的留言簿时,我遇到了另一个问题。
首先,请记住,显示的代码在 VS 或通过编译的 exe 中可以在开发机器上完美运行。
代码使用 Wacom Signature SDK 来捕获来自 pad(硬件设备)的签名,并且应该将其存储在 .png 格式的文件夹中,以便稍后将其粘贴到 .xlsx 文件中以及访客姓名和姓氏。
当在我的开发机器以外的任何其他机器上启动时,它会在保存 .png (sigObj.RenderBitmap) 或尝试打开 .xlsx 文件时挂起(Excel excel = new Excel(@"D:\Ewidencja\DB.xlsx" , 1);) (我试图禁用要求签名的代码,只是在 .xlsx 中输入文本,但它仍然挂起)
我什至在一台终端机器上安装了整个 VS2019 并在那里编译了代码并出现了同样的问题。更改文件夹路径,以管理员身份运行等 - 没有解决问题。代码似乎无法访问驱动器上的任何文件。
值得一提的是,在我的机器上,我在 2 个单独的驱动器上有 2 个分区。我测试过的机器只有一个带有一个分区的驱动器。下面的代码考虑了我的机器,经过测试的版本已将驱动器号更改为“C:”。
由于我不是专业程序员,请记住代码不是一流的,我 100% 意识到这一点 - 我只是没有足够的知识来更好地编写它。
不幸的是,Wacom SDK 并没有真正提供好的文档——只是示例代码(这是下面代码的基础)
编辑:下面显示的代码与我的主机上的完全一样。更改驱动器之间的目录以及更改它们的名称不会影响程序。
Edit2:在完全删除项目的 Excel 部分并只运行签名部分后,我让代码抛出异常:
System.Runtime.InteropServices.COMException: „Gdiplus error: Win32Error
(GLE=0x3)”
与“sigObj.RenderBitmap(...)”一致。
这并不能解释为什么我仍然无法使用下面的代码访问 Excel 文件,但可能有助于缩小问题的范围。
编辑 3:在 Wacom 的常见问题页面上找到
GDIplus error
This error could be caused by outputting to a file on a read-only folder such
as "C:\Program Files".
Preventative measures:
Avoid writing to a read-only directory (this might even be the directory in
which you are running your application)
Specify a full path name
Make sure the target folder itself exists
For further information please see Microsoft's list of Windows error codes
有趣的是,我尝试使用的文件夹都不是只读的......
执行场景:
1.User inputs Name and Surname in two separate text boxes.
2.User clicks "Sign"
3.Checkbox appears on Signature Pad
4.User checks the checkbox and clicks "Next" on Signature Pad
5.Signature area appears on Signature Pad
6.User signs and click "OK"
7.Signature is saved as .png
8.Name, surname, date, hour and .png is being placed in first empty row of .xlsx file
9.Signature Pad is reset to display empty screen, text boxes are emptied
代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Florentis;
using stdole;
using Aspose;
using Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;
using _Excel = Microsoft.Office.Interop.Excel;
namespace TestWizCapt_WPF
{
class Excel
{
string path = "";
_Application excel = new _Excel.Application();
Workbook wb;
Worksheet ws;
public string debug;
public string guestList;
public Excel(string path, int sheet)
{
this.path = path;
wb = excel.Workbooks.Open(path);
ws = wb.Worksheets[sheet];
}
public void currentGuestList()
{
guestList = "";
for (int i = 1; ws.Cells[i, 1].Value2 != null; i++)
{
if (ws.Cells[i, 4].Value2 == null)
{
guestList += ws.Cells[i, 1].Value2 + " " + ws.Cells[i, 2].Value2 + "\n";
}
}
}
public int nextEmptyRow()
{
int j = 1;
for (int i = 1; ws.Cells[i, 1].Value2 != null; i++)
{
j++;
}
return j;
}
public int signOutCell(string surname, string name)
{
int j = 1;
bool found = false;
for (int i = 1; (ws.Cells[i, 1].Value2 != null); i++)
{
;
/*debug += ws.Cells[i, 1].Value2 + " " + ws.Cells[i, 2].Value2 + " " + " " + ws.Cells[i, 4].Value2 + j.ToString() + "\n";
if (ws.Cells[i, 1].Value2 == name)
{
debug += "NAME \n";
}
if (ws.Cells[i, 2].Value2 == surname)
{
debug += "SURNAME \n";
}
if (ws.Cells[i, 4].Value2 == null)
{
debug += "NULL \n";
}*/
if (ws.Cells[i, 1].Value2 == name && ws.Cells[i, 2].Value2 == surname && ws.Cells[i, 4].Value2 == null)
{
debug += "found" + j.ToString() + "\n";
found = true;
break;
}
j++;
}
if (found)
{
return j;
}
else
{
return 0;
}
}
public void WriteCell(int i, int j, string input)
{
ws.Cells[i, j].Value2 = input;
}
public void pasteSignature(int i, int j, string path)
{
Microsoft.Office.Interop.Excel.Range oRange = ws.Cells[i, j];
float Left = (float)((double)oRange.Left);
float Top = (float)((double)oRange.Top);
ws.Shapes.AddPicture(@path, MsoTriState.msoFalse, MsoTriState.msoCTrue, Left, Top, 100, 75);
}
public void Save()
{
wb.Save();
}
public void SaveAs(string path)
{
wb.SaveAs(path);
}
public void Close()
{
wb.Close();
}
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : System.Windows.Window
{
bool ScriptIsRunning; // flag for UI button respones
WizardCallback Callback; // For wizard callback
tPad Pad; // Pad parameters
bool isCheck = false;
static string padFont = "Verdana";
DateTime now = DateTime.Now;
class tPad
{
public string Model;
public stdole.IFontDisp TextFont;
public stdole.IFontDisp ButtonFont;
public stdole.IFontDisp SigLineFont;
public int signatureLineY;
public int whoY;
public int whyY;
public int buttonWith;
public tPad(string model, int signatureLineY, int whoY, int whyY,
int textFontSize, int buttonFontSize, int signLineSize, int buttonWith)
{
this.Model = model;
this.signatureLineY = signatureLineY;
this.whoY = whoY;
this.whyY = whyY;
this.buttonWith = buttonWith;
this.TextFont = SetFontProperties(padFont, textFontSize);
this.ButtonFont = SetFontProperties(padFont, buttonFontSize);
this.SigLineFont = SetFontProperties(padFont, signLineSize);
}
private IFontDisp SetFontProperties(string fontName, int fontSize)
{
stdole.IFontDisp fnt = (stdole.IFontDisp)new stdole.StdFont();
fnt.Name = fontName;
fnt.Size = (decimal)fontSize;
return fnt;
}
}
private Florentis.WizCtl WizCtl;
private Florentis.SigCtl SigCtl;
public MainWindow()
{
InitializeComponent();
SigCtl = new SigCtl();
WizCtl = new Florentis.WizCtl();
WizCtl.Licence = "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3YmM5Y2IxYWIxMGE0NmUxODI2N2E5MTJkYTA2ZTI3NiIsImV4cCI6MjE0NzQ4MzY0NywiaWF0IjoxNTYwOTUwMjcyLCJyaWdodHMiOlsiU0lHX1NES19DT1JFIiwiU0lHQ0FQVFhfQUNDRVNTIl0sImRldmljZXMiOlsiV0FDT01fQU5ZIl0sInR5cGUiOiJwcm9kIiwibGljX25hbWUiOiJTaWduYXR1cmUgU0RLIiwid2Fjb21faWQiOiI3YmM5Y2IxYWIxMGE0NmUxODI2N2E5MTJkYTA2ZTI3NiIsImxpY191aWQiOiJiODUyM2ViYi0xOGI3LTQ3OGEtYTlkZS04NDlmZTIyNmIwMDIiLCJhcHBzX3dpbmRvd3MiOltdLCJhcHBzX2lvcyI6W10sImFwcHNfYW5kcm9pZCI6W10sIm1hY2hpbmVfaWRzIjpbXX0.ONy3iYQ7lC6rQhou7rz4iJT_OJ20087gWz7GtCgYX3uNtKjmnEaNuP3QkjgxOK_vgOrTdwzD-nm-ysiTDs2GcPlOdUPErSp_bcX8kFBZVmGLyJtmeInAW6HuSp2-57ngoGFivTH_l1kkQ1KMvzDKHJbRglsPpd4nVHhx9WkvqczXyogldygvl0LRidyPOsS5H2GYmaPiyIp9In6meqeNQ1n9zkxSHo7B11mp_WXJXl0k1pek7py8XYCedCNW5qnLi4UCNlfTd6Mk9qz31arsiWsesPeR9PN121LBJtiPi023yQU8mgb9piw_a-ccciviJuNsEuRDN3sGnqONG3dMSA";
// initialise Wizard script support
Callback = new WizardCallback(); // Callback provided via InteropAXFlWizCOM
Callback.EventHandler = null;
WizCtl.SetEventHandler(Callback);
ScriptIsRunning = false;
}
private void btnSign_Click(object sender, EventArgs e)
{
txtInfo.Text = "";
print("Sign...");
isCheck = false;
if (!ScriptIsRunning)
{
startWizard();
}
else
print("Script is already running");
}
private void btnSignout_Click(object sender, EventArgs e)
{
signoutVisitor();
}
private void btnCancel_Click(object sender, EventArgs e)
{
print("Cancel...");
if (ScriptIsRunning)
{
scriptCancelled();
}
else
print("Script is not running");
}
private void print(string txt)
{
txtInfo.Text += txt + "\r\n";
}
private void signoutVisitor()
{
txtInfo.Text = "";
Excel excel = new Excel(@"D:\Ewidencja\DB.xlsx", 1);
int Cell = excel.signOutCell(surname.Text, name.Text);
if (Cell == 0)
{
print("Nie znaleziono gościa");
}
else
{
print("Wypisano gościa");
excel.WriteCell(Cell, 4, now.ToString());
}
excel.currentGuestList();
txtCurrentGuestList.Text = excel.guestList;
excel.Save();
excel.Close();
name.Text = "";
surname.Text = "";
//print(excel.debug);
}
private void signVisitor()
{
Excel excel = new Excel(@"D:\Ewidencja\DB.xlsx", 1);
int Cell = excel.nextEmptyRow();
excel.WriteCell(Cell, 1, name.Text);
excel.WriteCell(Cell, 2, surname.Text);
excel.WriteCell(Cell, 3, now.ToString());
excel.pasteSignature(Cell, 5,"D:\\123\\sig1.png");
excel.currentGuestList();
txtCurrentGuestList.Text = excel.guestList;
excel.Save();
excel.Close();
name.Text = "";
surname.Text = "";
}
// Wizard script:
private void startWizard()
{
print("startWizard");
bool success = WizCtl.PadConnect();
if (success)
{
ScriptIsRunning = true;
print("Pad detected: " + WizCtl.PadWidth + " x " + WizCtl.PadHeight);
switch (WizCtl.PadWidth)
{
case 396:
Pad = new tPad("STU-300", 60, 200, 200, 8, 8, 16, 70); // 396 x 100
break;
case 640:
Pad = new tPad("STU-500", 300, 360, 390, 16, 22, 32, 110); // 640 x 800
break;
case 800:
Pad = new tPad("STU-520 or STU-530", 300, 360, 390, 16, 22, 32, 110); // 800 x 480
break;
case 320:
Pad = new tPad("STU-430 or ePad", 100, 130, 150, 10, 12, 16, 110); // 320 x 200
break;
default:
print("No compatible device found");
break;
}
print(Pad.Model);
step1();
}
else
print("Unable to connect to tablet");
}
private void scriptCompleted()
{
print("scriptCompleted");
SigObj sigObj = (SigObj)SigCtl.Signature;
if (sigObj.IsCaptured)
{
sigObj.set_ExtraData("AdditionalData", "C# Wizard test: Additional data");
String filename = "D:\\123\\sig1.png";
sigObj.RenderBitmap(filename, 200, 150, "image/png", 0.5f, 0xff0000, 0xffffff, -1.0f, -1.0f, RBFlags.RenderOutputFilename | RBFlags.RenderColor32BPP | RBFlags.RenderEncodeData);
WizCtl.Reset();
WizCtl.Display();
signVisitor();
}
closeWizard();
}
private void scriptCancelled()
{
print("scriptCancelled");
closeWizard();
}
private void closeWizard()
{
print("closeWizard()");
ScriptIsRunning = false;
WizCtl.Reset();
WizCtl.Display();
WizCtl.PadDisconnect();
Callback.EventHandler = null; // remove handler
WizCtl.SetEventHandler(Callback);
txtInfo.Text = "Poprawnie wpisano gościa";
}
private void step1()
{
WizCtl.Reset();
// insert checkbox
WizCtl.Font = Pad.TextFont;
WizCtl.AddObject(ObjectType.ObjectCheckbox, "Check", "centre", "middle", "Zapoznałem się z zasadami panującymi na obiekcie i zobowiązuję się do ich przestrzegania.", 2);
// insert the buttons
WizCtl.Font = Pad.ButtonFont;
WizCtl.AddObject(ObjectType.ObjectButton, "Cancel", "left", "bottom", "Anuluj", Pad.buttonWith);
WizCtl.AddObject(ObjectType.ObjectButton, "Next", "right", "bottom", "Dalej", Pad.buttonWith);
// set callback when a button is pressed
Callback.EventHandler = new WizardCallback.Handler(Step1_Handler);
WizCtl.SetEventHandler(Callback);
WizCtl.Display();
}
private void Step1_Handler(object clt, object id, object type)
{
switch (id.ToString())
{
case "Next":
{
if (isCheck)
step2();
break;
}
case "Cancel":
{
scriptCancelled();
break;
}
case "Check":
{
isCheck = !isCheck;
break;
}
default:
{
print("Unexpected pad event: " + id.ToString());
break;
}
}
}
private void step2()
{
WizCtl.Reset();
// insert message
WizCtl.Font = Pad.TextFont;
WizCtl.AddObject(ObjectType.ObjectText, "txt", "centre", "top", "Proszę złożyć podpis poniżej", null);
// insert a signature line
WizCtl.Font = Pad.SigLineFont;
if (Pad.Model == "STU-300")
{
WizCtl.AddObject(ObjectType.ObjectText, "txt", "left", Pad.signatureLineY, "X..............................", null);
}
else
{
WizCtl.AddObject(ObjectType.ObjectText, "txt", "centre", Pad.signatureLineY, "X..............................", null);
}
// insert the signature control
WizCtl.Font = Pad.TextFont;
WizCtl.AddObject(ObjectType.ObjectSignature, "Sig", 0, 0, SigCtl.Signature, null);
// provide who and why for sig capture
WizCtl.AddObject(ObjectType.ObjectText, "who", "right", Pad.whoY, name.Text +" " + surname.Text, null);
WizCtl.AddObject(ObjectType.ObjectText, "why", "right", Pad.whyY, "Poświadczam poprawność powyższych danych", null);
// insert the buttons
WizCtl.Font = Pad.ButtonFont;
if (Pad.Model == "STU-300")
{
WizCtl.AddObject(ObjectType.ObjectButton, "Cancel", "right", "top", "Anuluj", Pad.buttonWith);
//WizCtl.AddObject(ObjectType.ObjectButton, "Clear", "right", "middle", "Wyczyść", Pad.buttonWith);
WizCtl.AddObject(ObjectType.ObjectButton, "OK", "right", "bottom", "OK", Pad.buttonWith);
}
else
{
WizCtl.AddObject(ObjectType.ObjectButton, "Cancel", "left", "bottom", "Anuluj", Pad.buttonWith);
//WizCtl.AddObject(ObjectType.ObjectButton, "Clear", "center", "bottom", "Clear", Pad.buttonWith);
WizCtl.AddObject(ObjectType.ObjectButton, "OK", "right", "bottom", "OK", Pad.buttonWith);
}
// set callback when a button is pressed
Callback.EventHandler = new WizardCallback.Handler(Step2_Handler);
WizCtl.SetEventHandler(Callback);
WizCtl.Display();
}
private void Step2_Handler(object clt, object id, object type)
{
switch (id.ToString())
{
case "OK":
{
scriptCompleted();
break;
}
case "Clear":
{
break;
}
case "Cancel":
{
scriptCancelled();
break;
}
default:
{
print("Unexpected pad event: " + id.ToString());
break;
}
}
}
}
}