Разработчики из Windows Mobile Team в своем блоге анонсировали инструмент мониторинга использования API функций в приложениях для Windows Mobile – Windows Mobile API Usage Tool.
Windows Mobile API Usage Tool сканирует ваше приложение для Windows Mobile (в формате cab, msi, или просто бинарник), выполняет статический анализ (static analysis), и выдает отчет об использовании API и других системных ресурсов.
В дистрибутив также входит файл deprecated.txt, в котором содержится текущий список упраздненных (deprecated) функций для Windows Mobile. Можно также получить отчет об использовании этих функций в вашем приложении. Использование Windows Mobile API Usage Tool это эффективный способ проверить то, как ваше приложение будет себя вести если deprecated-функции будут удалены из Windows Mobile.
Windows Mobile API Usage Tool работает из командной строки и выдает результат в виде базы данных SQL Compact Edition (.sdf файл). При вызове с ключем /deprecated также генерируются несколько полезных отчетов.

Previous ArticleNext Article
Технический директор IT-Dimension, компании-разработчика кросс-платформенного программного обеспечения

Leave a Reply

Your email address will not be published. Required fields are marked *

К.

Как программно установить GPRS-соединение в Windows Mobile

Для того чтобы установить соединение с Internet в Windows Mobile предусмотрен специальный программный интерфейс – Connection Manager API.
Пользоваться им довольно просто. И вот пример такого использования для C# и C++ приведен ниже:

C# + .NET Compact Framework

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;

namespace GPRSConnection
{
    public class GPRSConnection
    {
        const int S_OK = 0;
        const uint CONNMGR_PARAM_GUIDDESTNET = 0x1;
        const uint CONNMGR_FLAG_PROXY_HTTP = 0x1;
        const uint CONNMGR_PRIORITY_USERINTERACTIVE = 0x08000;
        const uint INFINITE = 0xffffffff;
        const uint CONNMGR_STATUS_CONNECTED = 0x10;
        static Hashtable ht = new Hashtable();

        static GPRSConnection()
        {
            ManualResetEvent mre = new ManualResetEvent(false);
            mre.Handle = ConnMgrApiReadyEvent();
            mre.WaitOne();
            CloseHandle(mre.Handle);
        }

        ~GPRSConnection()
        {
            ReleaseAll();
        }

        public static bool Setup(Uri url)
        {
            return Setup(url.ToString());
        }

        public static bool Setup(string urlStr)
        {
            ConnectionInfo ci = new ConnectionInfo();
            IntPtr phConnection = IntPtr.Zero;
            uint status = 0;

            if (ht[urlStr] != null)
                return true;

            if (ConnMgrMapURL(urlStr, ref ci.guidDestNet, IntPtr.Zero) != S_OK)
                return false;

            ci.cbSize = (uint)Marshal.SizeOf(ci);
            ci.dwParams = CONNMGR_PARAM_GUIDDESTNET;
            ci.dwFlags = CONNMGR_FLAG_PROXY_HTTP;
            ci.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
            ci.bExclusive = 0;
            ci.bDisabled = 0;
            ci.hWnd = IntPtr.Zero;
            ci.uMsg = 0;
            ci.lParam = 0;

            if (ConnMgrEstablishConnectionSync(ref ci, ref phConnection, INFINITE, ref status) != S_OK &&
                status != CONNMGR_STATUS_CONNECTED)
                return false;

            ht[urlStr] = phConnection;
            return true;
        }

        public static bool Release(Uri url)
        {
            return Release(url.ToString());
        }

        public static bool Release(string urlStr)
        {
            return Release(urlStr, true);
        }

        private static bool Release(string urlStr, bool removeNode)
        {
            bool res = true;
            IntPtr ph = IntPtr.Zero;
            if (ht[urlStr] == null)
                return true;
            ph = (IntPtr)ht[urlStr];
            if (ConnMgrReleaseConnection(ph, 1) != S_OK)
                res = false;
            CloseHandle(ph);
            if (removeNode)
                ht.Remove(urlStr);
            return res;
        }

        public static void ReleaseAll()
        {
            foreach (DictionaryEntry de in ht)
            {
                Release((string)de.Key, false);
            }
            ht.Clear();
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ConnectionInfo
        {
            public uint cbSize;
            public uint dwParams;
            public uint dwFlags;
            public uint dwPriority;
            public int bExclusive;
            public int bDisabled;
            public Guid guidDestNet;
            public IntPtr hWnd;
            public uint uMsg;
            public uint lParam;
            public uint ulMaxCost;
            public uint ulMinRcvBw;
            public uint ulMaxConnLatency;
        }

        [DllImport("cellcore.dll")]
        private static extern int ConnMgrMapURL(string pwszURL, ref Guid pguid, IntPtr pdwIndex);

        [DllImport("cellcore.dll")]
        private static extern int ConnMgrEstablishConnectionSync(ref ConnectionInfo ci, ref IntPtr phConnection, uint dwTimeout, ref uint pdwStatus);

        [DllImport("cellcore.dll")]
        private static extern IntPtr ConnMgrApiReadyEvent();

        [DllImport("cellcore.dll")]
        private static extern int ConnMgrReleaseConnection(IntPtr hConnection, int bCache);

        [DllImport("coredll.dll")]
        private static extern int CloseHandle(IntPtr hObject);
    }
}

Пример использования

public void DoTcpConnection()
        {
            string t = System.IO.Path.AltDirectorySeparatorChar.ToString() + System.IO.Path.DirectorySeparatorChar.ToString();
            string url = "www.msn.com";
            bool res = GPRSConnection.Setup(Uri.UriSchemeHttp + 
                Uri.SchemeDelimiter + url + Path.AltDirectorySeparatorChar);
            if (res)
            {
                TcpClient tc = new TcpClient(url, 80);
                NetworkStream ns = tc.GetStream();
                byte[] buf = new byte[100];
                ns.Write(buf, 0, 100);
                tc.Client.Shutdown(SocketShutdown.Both);
                ns.Close();
                tc.Close();
                MessageBox.Show("Wrote 100 bytes");
            }
            else
            {
                MessageBox.Show("Connection establishment failed");
            }
        }

C++

Singleton.h
#ifndef _SINGLETON_H
#define _SINGLETON_H

template<typename T> class Singleton
{
public:
	static T & Instance()
	{
		static T instance;
		return instance;
	}
};

#endif
GPRSConnection.h
#pragma once

#include <windows.h>
#include <connmgr.h>
#include <map>
#include "Singleton.h"

class GPRSConnection : public Singleton<GPRSConnection>
{
	friend class Singleton<GPRSConnection>;
#ifndef _UNICODE
	typedef std::string StringType;
#else
	typedef std::wstring StringType;
#endif
	bool apiReady;
	std::map<StringType, HANDLE> Connections;
protected:
	GPRSConnection() : apiReady(false)
	{
		do
		{
			HANDLE apiHandle = ConnMgrApiReadyEvent();
			if(!apiHandle) break;
			if(WaitForSingleObject(apiHandle, 10000) != WAIT_OBJECT_0) break;
			CloseHandle(apiHandle);
			apiReady = true;
		}
		while(false);
	}
public:
	~GPRSConnection()
	{
		ReleaseAll();
	}

	bool Setup(LPCTSTR url)
	{
		StringType urlInternal = url;
		if(Connections[urlInternal] != NULL) return true;
		CONNMGR_CONNECTIONINFO ci;
		if(ConnMgrMapURL(url, &ci.guidDestNet, NULL) != S_OK) return false;
		ci.cbSize = sizeof(CONNMGR_CONNECTIONINFO);
		ci.dwParams = CONNMGR_PARAM_GUIDDESTNET;
		ci.dwFlags = CONNMGR_FLAG_PROXY_HTTP;
		ci.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
		ci.bExclusive = 0;
		ci.bDisabled = 0;
		ci.hWnd = NULL;
		ci.uMsg = 0;

		DWORD status = CONNMGR_STATUS_UNKNOWN;
		HANDLE phConnection;
		if (ConnMgrEstablishConnectionSync(&ci, &phConnection, -1, &status) != S_OK &&
			status != CONNMGR_STATUS_CONNECTED) return false;

		Connections[urlInternal] = phConnection;
		return true;
	}

	bool Release(LPCTSTR url, bool removeNode)
	{
		StringType urlInternal = url;
		bool res = true;
		if(Connections[urlInternal] == NULL) return true;
		if (ConnMgrReleaseConnection(Connections[urlInternal], 1) != S_OK) res = false;
		CloseHandle(Connections[urlInternal]);
		if(removeNode)
		{
			Connections.erase(urlInternal);
		}
		else 
		{
			Connections[urlInternal] = NULL;
		}
		return res;
	}

	void ReleaseAll()
	{
		for(std::map<StringType, HANDLE>::iterator i = Connections.begin(); i != Connections.end(); ++i)
		{
			Release(i->first.c_str(), false);
		}
		Connections.clear();
	}
};

Пример использования

void MainFrame::OnCONNECTClick( wxCommandEvent& event )
{
	TransferDataFromWindow();
	bool res = GPRSConnection::Instance().Setup(m_URL.GetData());
	if(res)
	{
		wxLogMessage(_("Connection established"));
		// Дальше здесь можно делать всякие штуки
	}
	else
	{
		wxLogMessage(_("Connection error"));
	}
}

Скачать исходный код к статье (C++/C#)

w.

winChain Builder – Windows инструментарий разработчика приложений для iPhone

А ведь вот как оказывается, для того чтобы писать под iPhone не обязательно иметь Мак, а достаточно PC под управлением Windows. Недавно наткнулся на сайт проекта winChain Builder.

winChain Builder – это инструментарий разработчика (набор заголовочных файлов, библиотек, компилятор и несколько дополнительных утилит для создания проекта) на базе Cygwin, который позволяет писать приложения для iPhone в Windows.

Учитывая тот факт, что Apple всеми силами старается навязать принцип “хочешь писать для iPhone – покупай Мак”, удобство winChain Builder, конечно же не так высоко, как хотелось бы.
Ради интереса попробовал создать тестовый проект, но для начала все это добро надо было установить.

Для установки winChain Builder используется самописная утилита (на вид, написанная на C# ;)), которая просто устанавливает Cygwin и копирует заголовочные файлы и библиотеки. Также есть возможность установить Notepad++ как редактора кода с подсветкой синтаксиса Objective-C.

Для того чтобы создать новый проект в дистрибутиве есть специальная утилита – winChain Template Builder. В ней необходимо указать папку, где будут созданы файлы проекта, название проекта, а также имя разработчика. И все. В результате получаем шаблон минимального приложения для iPhone, которое из Cygwin собирается одной командой make.

WinChain Template Builder - Создание проекта для iPhone в Windows
WinChain Template Builder - Создание проекта для iPhone в Windows

Собрать минимальное приложение у меня получилось, а вот оттестировать его, к сожалению, нет. С этим пока проблема, эмуляторов iPhone под Windows с возможностью запускать нативные приложения мне найти так и не удалось, а продажи последней модели iPhone у нас пока не начались, так что ждем-с… 🙂

И по сему у меня небольшая просьба к читателям этого блога: уважаемые товарищи счастливые обладатели iPhone’ов, кто хочет потестировать минимальное приложение, собранное с помощью winChain Builder, так сказать, ради академического интереса? Если есть кто-то, кто может помочь с этим, отпишите мне plz.

Ссылка по теме:

Сайт проекта winChain Builder