【发布时间】:2014-12-04 00:53:29
【问题描述】:
我曾打算实现 Manzana.dll 库以检测 iPhone 连接事件并与设备交互。问题是它似乎只有在客户端机器安装了 iTunes dll 和资源时才有效,我不能依赖这些。因此,我尝试使用 Manzana 源代码的自定义实现来指向它对我包含在项目中的必要 iTunes 文件的引用。
虽然看起来一切正常,但在我的应用程序中使用编译库时会引发 NullReferenceException。应用程序加载并初始化正常,但是当连接 iPhone 时,connectedevent 会抛出异常。
实际错误是:
System.TypeInitializationException: The type initializer for 'istreamwrapper.MobileDevice' threw an exception. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at istreamwrapper.MobileDevice..cctor()
--- End of inner exception stack trace ---
at istreamwrapper.MobileDevice.AMDeviceNotificationSubscribe(DeviceNotificationCallback callback, UInt32 unused1, UInt32 unused2, UInt32 unused3, Void*& am_device_notification_ptr)
at istreamwrapper.iPhone.doConstruction()
我能够使用它来将问题从我的 iPhone 类中缩小到此方法
private unsafe void doConstruction()
{
void* voidPtr;
this.dnc = new DeviceNotificationCallback(this.NotifyCallback);
this.drn1 = new DeviceRestoreNotificationCallback(this.DfuConnectCallback);
this.drn2 = new DeviceRestoreNotificationCallback(this.RecoveryConnectCallback);
this.drn3 = new DeviceRestoreNotificationCallback(this.DfuDisconnectCallback);
this.drn4 = new DeviceRestoreNotificationCallback(this.RecoveryDisconnectCallback);
int num = MobileDevice.AMDeviceNotificationSubscribe(this.dnc, 0, 0, 0, out voidPtr);
if (num != 0)
{
throw new Exception("AMDeviceNotificationSubscribe failed with error " + num);
}
num = MobileDevice.AMRestoreRegisterForDeviceNotifications(this.drn1, this.drn2, this.drn3, this.drn4, 0, null);
if (num != 0)
{
throw new Exception("AMRestoreRegisterForDeviceNotifications failed with error " + num);
}
this.current_directory = "/";
}
}
问题来自于
num = MobileDevice.AMDeviceNotificationSubscribe(this.dnc, 0, 0, 0, out voidPtr);
它指向位于我的 MobileDevice 类中的代码
[DllImport("iTunesMobileDevice.dll", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int AMDeviceNotificationSubscribe(DeviceNotificationCallback callback, uint unused1, uint unused2, uint unused3, out void* am_device_notification_ptr);
这似乎又在它自己的类中引用了这个
namespace istreamwrapper
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void DeviceNotificationCallback(ref AMDeviceNotificationCallbackInfo callback_info);
}
然后指向另一个类:
namespace istreamwrapper
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct AMDeviceNotificationCallbackInfo
{
internal unsafe void* dev_ptr;
public NotificationMessage msg;
public unsafe void* dev
{
get
{
return this.dev_ptr;
}
}
}
}
大部分代码是直接从 Manzana.dll 复制的,我唯一更改的是 itunesmobiledevice 文件所在的位置(现在是设置路径,而不是在运行时检测到)
旧代码:
namespace Manzana
{
internal class MobileDevice
{
private static readonly FileInfo iTunesMobileDeviceFile = new FileInfo(Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Apple Inc.\\Apple Mobile Device Support\\Shared", "iTunesMobileDeviceDLL", (object) "iTunesMobileDevice.dll").ToString());
private static readonly DirectoryInfo ApplicationSupportDirectory = new DirectoryInfo(Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Apple Inc.\\Apple Application Support", "InstallDir", (object) Environment.CurrentDirectory).ToString());
private const string DLLName = "iTunesMobileDevice.dll";
static MobileDevice()
{
string str = MobileDevice.iTunesMobileDeviceFile.DirectoryName;
if (!MobileDevice.iTunesMobileDeviceFile.Exists)
{
str = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + "\\Apple\\Mobile Device Support\\bin";
if (!File.Exists(str + "\\iTunesMobileDevice.dll"))
str = "C:\\Program Files\\Common Files\\Apple\\Mobile Device Support";
}
Environment.SetEnvironmentVariable("Path", string.Join(";", new string[3]
{
Environment.GetEnvironmentVariable("Path"),
str,
MobileDevice.ApplicationSupportDirectory.FullName
}));
}
新代码:
namespace istreamwrapper
{
class MobileDevice
{
static MobileDevice()
{
string str = "[XX_MYPATHHERE_XX]\\Apple\\Mobile Device Support";
string AppSuppDirectory = @"[XX_MYPATHHERE_XX]\Apple\Apple Application Support";
Environment.SetEnvironmentVariable("Path", string.Join(";", new string[3] { Environment.GetEnvironmentVariable("Path"), str, AppSuppDirectory }));
}
我缺少什么导致该调用返回 null 吗?我承认我并不完全理解上面代码中发生的所有事情,所以完全有可能它很简单。
【问题讨论】:
-
其实我可能已经解决了。我不知道为什么它会抛出一个通用的空异常,但我把那个代码拿出来并单独测试它给了我一个 dllnotfound 错误,这更有帮助。我已经更改了一条路径,明天将进行测试,看看是否解决了它。
-
我也在找同样的东西你能帮我吗...
标签: c# iphone itunes dllimport mobile-devices