私は Windows CE アプリをしばらくの間 (1 年以上) 保守しており、その新しいバージョンを時々作成し、それらをハンドヘルド デバイスにコピーして、そこで新しいバージョンを実行しています。
しかし、今日、初めて新しい 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
[プロジェクト] > [プロパティ...] で、プラットフォームが「アクティブ (任意の CPU)」に設定され、プラットフォーム ターゲットが同じ (「アクティブ (任意の CPU)」) に設定されます。
これは間違っている、「x86」であるべきだと読みましたが、利用可能な「x86」オプションはありません - すべての CPU が唯一のものです...?!?
更新 6
[プロジェクト] > [プロパティ...] > [デバイス] で、[最新バージョンの .NET Compact Framework (Service Pack を含む) を展開する] にチェックが入っています。これはあるべき姿ですか?
更新 7
さて、これがすべての本当に奇妙な部分です:
Motorola/Symbol 3090 および 3190 ハンドヘルド デバイスで実行する必要がある 2 つの CF/CE アプリがあります。
One is this simple utility discussed above. I find that it actually does run on one of the devices (the 3190, FWIW). So it runs on one device, but not on the other.
ただし、もう 1 つの (レガシー) .exe は逆です。3090 (ユーティリティが起動さえしない) では実行されますが、3190 では実行されません。
したがって、ユーティリティのニーズは 3190 で満たされ、レガシー ユーティリティのニーズは 3090 で満たされます。ただし、レガシー アプリの新しいバージョンはどちらのデバイスでも実行されません。
私は困惑しています。ケイシー・ステンゲルが彼の 3 人のキャッチャーについて語ったとき、次のように感じたに違いありません。 "
更新 8
3190 には新しいバージョンの CF がインストールされています。新しいアプリと古いアプリの両方が、新しい CE を搭載した新しいデバイスで実行されるはずですが、そうではありません。新しいフレームワークに対して/のために構築されたものだけが実行されます...
更新 9
3090 の外観は次のとおりです。
更新 10
そのため、2 つの exe があります。1 つはデバイス上で実行され (両方とも現在)、もう 1 つはどちらのデバイスでも実行されません。2 つの exesw はほとんど同じように見えます。それらを次の 3 つのツールと比較しました。Red Gates の .NET Reflector。JetBrains の dotPeek と Dependency Walker。
これが私が見つけたものです:
依存関係ウォーカー どちらも、依存関係の欠落について同じエラーがあるようです (依存アセンブリと同じフォルダーにそれらを持っていなかったことがおそらく問題です)
.NET Reflector 非作業ファイルには、作業ファイルにはない次のエントリがあります。
[assembly: Debuggable(0x107)]
これが問題ですか? もしそうなら、どうすれば変更できますか?
JetBrains dotpeekEXE の作業コピーの参照はすべてバージョン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 を動作するものと一致するように変更するにはどうすればよいですか?
これは主に、プロジェクトの動作していない (新しい) バージョンに「4.5」文字列が存在する場所が見当たらないためです。dotPeek はどこでその情報を取得できますか?
更新 11
問題はこれら 2 つの 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」ピルをマッシュすることで(ボタンがどのように見えますか - 「ロゼンジ」) - それは、2つの方法のMessagebox.show()sをデバッグするように、Gerbilsのタップダンスのように聞こえます。そして、AD Infinitum AD(文字通り)吐き気)。