1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

WindowsでiPhoneのデベロッパモードを有効にする方法

Posted at

iOS16からデベロッパモードが導入

iOS16からiPhoneで開発する際には「デベロッパモード」を有効にする必要があります。
https://qiita.com/YokohamaHori/items/d00e1786c34b4ab30638

iOS16βではデフォルトで「設定」にデベロッパモードの項目が表示されていますが、製品版では表示されなくなったようです。

原則としてMac(XCode入り)につないで項目を表示させてから、ONにする必要があります。
(↑ この部分で何らかの命令を飛ばしている?)

Windowsのみでデベロッパモードを有効にする

通常はiPhoneの開発をするのにMacがないなんて考えられないのですが、なんやかんやあって、WindowsのみでデベロッパモードをONにする必要が生じました。

iOSデバイス用のオープンソースライブラリであるlibimobiledeviceでは、対応してそうなissueがありますが、windows用のビルドが通らない & nuget版も長らく更新していない。

  • 方針 とりあえず既存のlibimobiledeviceのDLLを叩いて、無理やりデベロッパモードを出現させる。

コーディング

前提

  • VisualStudioとC#を使用します。
  • nugetでlibimobiledeviceをインストールします。
  • 適当なクラスを作成してそのメソッドとして構築しています。(以下ではIosDeviceクラスとして作成)
//iPhoneを識別するためのudid
private readonly string udid;
//libimobiledeviceのAPIを叩くための宣言
private IScreenshotrApi sc;
private ScreenshotrClientHandle clientHandle;

//コンストラクタ
public IosDevice()
{
    NativeLibraries.Load();
    //まずUDIDの取得
    int count = 0;
    IiDeviceApi idevice = LibiMobileDevice.Instance.iDevice;
    iDeviceError ret = idevice.idevice_get_device_list(out ReadOnlyCollection<string> udids, ref count);
    if (ret == iDeviceError.NoDevice)
    {
        throw new Exception("Connot recognize iOS devices.");
    }
    ret.ThrowOnError();
    if (udids.Count == 0)
    {
        throw new Exception("Connot recognize iOS devices.");
    }
    //2台以上接続は不可
    if (udids.Count > 1)
    {
        throw new Exception("Do not connect multiple devices.");
    }
    this.udid = udids[0];
}

iOSバージョンの取得

    //libimobiledeviceのexeファイルのCコードを、C#に改造しています
    NativeLibraries.Load();
    IiDeviceApi idevice = LibiMobileDevice.Instance.iDevice;
    iDeviceHandle deviceHandle;
    //今後、ほとんどのメソッドは、引数にoutを指定して結果を保存している(戻り値は成否)
    try
    {
        //デバイスハンドルの取得
        idevice.idevice_new(out deviceHandle, this.udid).ThrowOnError();
    }
    catch (Exception ex)
    {
        throw ex;
    }
    ILockdownApi lockdown = LibiMobileDevice.Instance.Lockdown;
    LockdownClientHandle lockdownHandle;
    try
    {
        //ロックダウンハンドルの取得
        lockdown.lockdownd_client_new_with_handshake(deviceHandle, out lockdownHandle, "AP");
    }
    catch
    {
        throw new Exception("Connot recognize iOS devices.");
    }
    //iOSのバージョンを取得
    string version;
    try
    {
        lockdown.lockdownd_get_value(lockdownHandle, null, "ProductVersion", out tested);
        tested.Api.Plist.plist_get_string_val(tested, out version);
    }
    catch(Exception ex)
    {   
        throw new Exception(ex.Message);
    }
    int majorVersion;
    //iOSのバージョン表記は〇.〇.〇
    Int32.TryParse(version.Split('.')[0], out majorVersion);

iOSバージョンが16以上の場合デベロッパモードを表示

//iOS16以上の場合は開発モード必須
if (majorVersion >= 16){
    //デベロッパモードの状態取得
    if (lockdown.lockdownd_get_value(lockdownHandle,
        "com.apple.security.mac.amfi", "DeveloperModeStatus", out PlistHandle devMode) != LockdownError.Success)
    {
        throw new Exception("Failed to acquire developer mode.");
    }
    //デベロッパモードが無効の場合、有効化
    char dev_mode_status = '\0';
    devMode.Api.Plist.plist_get_bool_val(devMode, ref dev_mode_status);
    if (dev_mode_status == '\0')
    {
        if (lockdown.lockdownd_start_service(lockdownHandle, "com.apple.amfi.lockdown",
            out LockdownServiceDescriptorHandle amfiService) != LockdownError.Success)
        {
            throw new Exception("Failed to acquire developer mode service.");
        }
        IPropertyListServiceApi pList = LibiMobileDevice.Instance.PropertyListService;
        if (pList.property_list_service_client_new(deviceHandle, amfiService,
            out PropertyListServiceClientHandle amfi) != PropertyListServiceError.Success)
        {
            throw new Exception("Failed to acquire developer status.");
        }
        PlistHandle dict = devMode.Api.Plist.plist_new_dict();
        // devMode.Api.Plist.plist_new_uintの値
        // 1 = 自動ON(パスコードなし時のみ可能)0 = 項目表示のみ
        devMode.Api.Plist.plist_dict_set_item(dict, "action", devMode.Api.Plist.plist_new_uint(0));
        if (pList.property_list_service_send_xml_plist(amfi, dict) != PropertyListServiceError.Success)
        {
            throw new Exception("Request to display DeveloperMode failed.");
        }
        if (pList.property_list_service_receive_plist(amfi, out dict) != PropertyListServiceError.Success)
        {
            throw new Exception("Request to display DeveloperMode denied.");
        }
        PlistHandle errorValue = devMode.Api.Plist.plist_dict_get_item(dict, "Error");
        if (!errorValue.IsInvalid)
        {
            devMode.Api.Plist.plist_get_string_val(errorValue, out string err);
            throw new Exception("An error occurred when changing DeveloperMode.\n" + err);
        }
        
        PlistHandle val = devMode.Api.Plist.plist_dict_get_item(dict, "success");
        char success = '0';
        if (!val.IsInvalid)
        {
            devMode.Api.Plist.plist_get_bool_val(val, ref success);
        }
        if (success == '0')
        {
            throw new Exception("Failed to display DeveloperMode.");
        }
    }
}





1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?