我一直在维护一个 Windows CE 应用程序一段时间(一年多),并且不时生成它的新版本,将它们复制到手持设备并在那里运行新版本。
不过,今天,我第一次创建了一个新的 Windows CE 应用程序。这是一个非常简单的实用程序。
为了在 VS 2008 中创建它,我选择了一个 C#“智能设备项目”模板,添加了一些控件和一些代码,然后构建了它。
以下是我选择的一些选项:
我将通过构建项目生成的 .exe 复制到手持设备的 Program Files 文件夹中:
...但它不会运行。是不是在错误的位置?是否需要复制一些辅助文件?我需要做一些其他的设置才能让它运行吗?要不然是啥?
更新
由于内容不多,我将粘贴下面的所有代码,以防有人认为我的代码可能是问题所在:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace PrinterCommanderCE
{
public partial class PrinterCommanderForm : Form
{
public PrinterCommanderForm()
{
InitializeComponent();
}
private void btnSendCommands_Click(object sender, EventArgs e)
{
SendPrinterCommands();
}
private void SendPrinterCommands()
{
bool successfulSend = false;
const string quote = "\"";
string keepPrinterOn = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}off{0}", quote);
string shutPrinterOff = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}on{0}", quote);
string advanceToBlackBar = string.Format("! U1 setvar {0}media.sense_mode{0} {0}bar{0}", quote);
string advanceToGap = string.Format("! U1 setvar {0}media.sense_mode{0} {0}gap{0}", quote);
if (radbtnBar.Checked)
{
successfulSend = SendCommandToPrinter(advanceToBlackBar);
}
else if (radbtnGap.Checked)
{
successfulSend = SendCommandToPrinter(advanceToGap);
}
if (successfulSend)
{
MessageBox.Show("label type command successfully sent");
}
else
{
MessageBox.Show("label type command NOT successfully sent");
}
if (ckbxPreventShutoff.Checked)
{
successfulSend = SendCommandToPrinter(keepPrinterOn);
}
else
{
successfulSend = SendCommandToPrinter(shutPrinterOff);
}
if (successfulSend)
{
MessageBox.Show("print shutoff command successfully sent");
}
else
{
MessageBox.Show("print shutoff command NOT successfully sent");
}
}
private bool SendCommandToPrinter(string cmd)
{
bool success = false;
try
{
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd);
serialPort.Close();
success = true;
}
catch
{
success = false;
}
return success;
}
}
}
更新 2
基于此,我向应用程序添加了一个全局异常处理程序,因此 Program.cs 现在是:
namespace PrinterCommanderCE
{
static class Program
{
[MTAThread]
static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
Application.Run(new PrinterCommanderForm());
}
static void GlobalExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
MessageBox.Show(string.Format("GlobalExceptionHandler caught : {0}", e.Message));
}
}
}
然而,运行新版本并没有显示任何内容——它只是在 Jack Ruby 的友好访问之后短暂地“闪烁”了与 Lee Harvey Oswald 一样多的冗长。
更新 3
问题是否与此有关,如果是,如何解决?
我的现有应用程序的更新版本和这个全新的简单应用程序都拒绝运行的情况表明,在编码、构建或部署过程中的某个地方存在根本缺陷。
更新 4
由于这是一个最小的实用程序,它(以及我的遗留,涉及更多)应用程序无法运行的原因可能与项目属性、构建方式、未复制所需文件或...... ???
注意:桌面图标是“通用的”(看起来像一个空白的白色表格);这可能表明存在问题,但它是否表明有问题或者是一个小问题(仅限美学)?
更新 5
在 Project > Properties... 中,Platform 设置为“Active (Any CPU)”和 Platform target 相同(“Active (Any CPU)”)
我读过这是错误的,它应该是“x86”,但没有可用的“x86”选项 - 任何 CPU 都是唯一的......?!?
更新 6
在项目 > 属性... > 设备中,选中“部署最新版本的 .NET Compact Framework(包括服务包) ”。这是应该的吗?
更新 7
好的,这是所有这一切中真正奇怪的部分:
我有两个 CF/CE 应用程序需要在这些 Motorola/Symbol 3090 和 3190 手持设备上运行。
一个是上面讨论的这个简单的实用程序。我发现它确实可以在其中一台设备(3190,FWIW)上运行。所以它在一台设备上运行,但不在另一台设备上运行。
但是,另一个(旧版).exe 则相反 - 它在 3090 上运行(该实用程序甚至不会启动),但不在 3190 上。
因此,3190 满足了实用程序的需求,3090 满足了旧版实用程序的需求。但是,旧版应用程序的新版本不能在任何设备上运行!
我很困惑;在谈到他的三个接球手时,我的感觉就像凯西·斯坦格尔(Casey Stengel)所说的那样:“我有一个会投但不会接球,一个会接球但不会投球,还有一个会击球但两者都不会。 "
更新 8
3190 安装了更新版本的 CF;似乎新旧应用程序都应该在具有较新 CE 的新设备上运行,但它们不会——只有针对/为新框架构建的应用程序才可以......
更新 9
这是 3090 的外观:
更新 10
所以我有两个 exe,一个在设备上运行(现在都在),另一个在这两个设备上都不运行。这两个exesw似乎几乎相同。我将它们与三个工具进行了比较:Red Gates 的 .NET Reflector;JetBrains 的 dotPeek 和 Dependency Walker。
这是我发现的:
Dependency Walker 两者似乎都有关于缺少依赖项的相同错误(我没有将它们与它们的依赖程序集放在同一个文件夹中,这可能是那里的问题)
.NET Reflector 非工作文件具有工作文件没有的以下条目:
[assembly: Debuggable(0x107)]
这是问题吗?如果是,我该如何改变它?
JetBrains dotPeek exe工作副本中的References都是1.0.50000.0版本
非工作 exe 具有相同的参考列表和相同的版本号。
但是有这个区别:
对于工作的 .exe,dotPeek 说,“ 1.4.0.15,msil,Pocket PC v3.5 ” 对于非工作的 .exe,dotPeek 说,“ 1.4.0.15,msil,.Net Framework v4.5 ”
这是问题吗?如果是,我该如何更改非工作的 .exe 以匹配工作的 .exe?
最后一个令人不安,主要是因为我在项目的非工作(较新)版本中没有看到存在“4.5”字符串的地方。dotPeek 可以从哪里获得这些信息?
更新 11
我现在确实知道问题出在这两个 MessageBox.Show() 之间,因为我看到的第一个,但不是第二个:
public static int Main(string [] args)
{
try
{
// A home-brewed exception handler (named ExceptionHandler()) is already defined, but I'm adding a global one
// for UNHANDLED exceptions (ExceptionHandler() is explicitly called throughout the code in catch blocks).
MessageBox.Show("made it into Main method"); // TODO: Remove after testing <= this one is seen
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
string name = Assembly.GetExecutingAssembly().GetName().Name;
IntPtr mutexHandle = CreateMutex(IntPtr.Zero, true, name);
long error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
{
ReleaseMutex(mutexHandle);
IntPtr hWnd = FindWindow("#NETCF_AGL_BASE_",null);
if ((int) hWnd > 0)
{
SetForegroundWindow(hWnd);
}
return 0;
}
ReleaseMutex(mutexHandle);
DeviceInfo devIn = DeviceInfo.GetInstance();
Wifi.DisableWifi();
// Instantiate a new instance of Form1.
frmCentral f1 = new frmCentral();
f1.Height = devIn.GetScreenHeight();
f1.Text = DPRU.GetFormTitle("DPRU HHS", "", "");
MessageBox.Show("made it before Application.Run() in Main method"); // TODO: Remove after testing <= this one is NOT seen
Application.Run(f1);
devIn.Close();
Application.Exit();
return 0;
}
catch(Exception ex)
{
DPRU.ExceptionHandler(ex, "Main");
return 0;
}
} // Main() method
更新 12
更具体地说,我以某种方式进行了无限循环;通过在手持设备上捣碎“Ent”药丸(这就是按钮的样子——“菱形”)——听起来像是沙鼠踢踏舞(因为在两种方法中调试 MessageBox.Show()s 时弹出并被关闭和无限广告(字面意思)恶心)。