symbian 2nd如何绕过程序管理器的限制
来源:互联网 发布:疯狂美工注册码 编辑:程序博客网 时间:2024/05/16 05:54
symbian 2nd如何绕过程序管理器的限制
北京理工大学 20981 陈罡
在symbian开发中我们经常会用到手机系统自带的“程序管理”这个软件。这个软件的功能在于它会忠实地把程序的安装操作记录下来,在删除程序的时候它也会忠实地把程序给删除。这种做法对于symbian来说,无疑是最好的选用第三方软件的选择,既可以安装到手机上,又可以无条件的将软件卸载掉。
但是这个所谓的“程序管理”,也有很多弊端。例如,每次都需要把程序的安装包拷贝到“手机存储”上去,这样安装包一旦大于
在这里我要讨论一种方式,可以绕过程序管理器的限制,在“程序管理”器里面没有记录,也无法把程序从程序管理器里面卸载,这种方式虽然比较有效,但是程序的卸载操作就需要使用其它的单独的卸载程序才能卸载了。
绕过程序管理器的方法其实很简单,自己编写一个程序管理器即可。很多朋友会想编写一个程序管理器多么多么的复杂,需要熟悉sis文件格式之类的内容。其实一点也不复杂,sis本身就是s60自带的程序管理器支持的文件格式,只有nokia的程序管理器才能够识别。既然我们自己编写程序管理器的话,就不必拘泥于sis格式了。自己的程序可以读取的文件格式就可以自己说得算了。
我们知道在创建pkg文件的时候,在需要安装后立即运行的程序后面通常只要指定一个RI,FI,就可以保证程序在安装后可以立即执行,例如:"marm/myapp.exe"-"!:/System/Apps/MyApp/Myapp.exe",RI,FI
这样就提供了一个方法摆脱当前的程序管理器的方法,大致的思路如下:编写一个exe文件,该文件可以将某个.zip或者.dat的包解压缩到手机的e:/system/apps目录下面即可。
整体的写下来,大概是这个样子的:"marm/my.zip"-"!:/System/Apps/MyApp/my.zip""marm/myapp.exe"-"!:/System/Apps/MyApp/myapp.exe",RI,FI在myapp.exe运行的时候,可以给它加入适当的1秒至3秒的延时,用来确保手机的程序管理器已经把zip包释放到某个目录下面去了,然后再开始运行myapp.exe,它的作用在于直接把my.zip包中的文件解压缩到system/apps目录或者希望可以开机自动运行的可以把相关的mdl文件考入c:/system/recogs目录。
注意:利用mdl在手机启动的时候自动载入的特性实现的所谓“开机自动运行”,在symbian 3rd平台中已经不再适用,以下是官方的issues说明:
这样一来,只有my.zip和myapp.exe这两个文件是纳入手机的应用程序管理器的控制范畴的,可以很容易地通过应用程序管理器删除,但是通过myapp.exe从my.zip中解压缩出来的,放入system/apps里面的目录则成功的逃脱了程序管理器的限制,保留了下来。这样就基本上实现了,程序脱离应用程序管理器的限制了。如果在my.zip中加入自动运行的mdl,然后调用自动登陆、下载zip、自动解压缩的程序的话,就可以实现程序的自动更新了。每次让开机自动运行的程序,在收到更新短信时启动,联网,下载更新包,然后解压缩安装。这一切都是以后台的方式运行的,不会对用户产生困扰,也不需要用户每次都通过nokia pc套件来下载,安装程序的繁琐过程。
对用户来说,只是某天突然发现不知道什么时候手机中多了一个应用程序的图标 :),或者发现某个程序的图标不见了(可以通过网络自动删除手机中的某个无效的应用)。相当于自己实现了一个OTA了。
相关实验我已经完全测试成功,呵呵。但是这种OTA是一把双刃剑不希望落入某些居心不良的人的手中,扰乱这个技术的发展。所以就暂时不开放代码了,只是把解压缩my.zip的myapp.exe代码开放一下,希望对有兴趣的朋友有用:
// --------------------------------------------------------------------------// zagzip.cpp//// programmer :
#include <e32base.h>#include <e32std.h>#include <f32file.h> // RFs and RFile#include <zipfile.h> // CZipFile#include <apacmdln.h> // CApaCommandLine#include <EikDll.h> // EDll::StartApp(...)#include <apgcli.h>#include <apgtask.h>#include <s32file.h> // RFileReadStream, RFileWriteStream
// use 4k buffer size #define BUF_SIZE 1024 * 4
// the specified zip config file name#ifndef __WINS___LIT(KZipPathnameC, "c://my.zip") ;_LIT(KZipPathnameE, "e://my.zip") ; _LIT(KExtractPath, "c://system//apps//abc//") ;_LIT(KSrcPathname, "c://system//apps//abc//abc.mdl") ;_LIT(KObjPathname, "c://system//recogs//abc.mdl") ;_LIT(KOutCmd, "c://system//apps//abc//abc.app") ; #else _LIT(KZipPathnameC, "c://my.zip") ;_LIT(KZipPathnameE, "c://my.zip") ; _LIT(KExtractPath, "c://system//apps//abc//") ;_LIT(KSrcPathname, "c://system//apps//abc//abc.mdl") ;_LIT(KObjPathname, "c://recogs//abc.mdl") ;_LIT(KOutCmd, "c://system//apps//abc//abc.app") ; #endif
TBuf8<BUF_SIZE> g_buf ; TBuf<100> g_zip_pathname ; TBuf<100> g_target_path ;TBuf<100> g_copy_src_pathname ; TBuf<100> g_copy_obj_pathname ;TBuf<100> g_run_command ;
// ConstantsLOCAL_C TBool check_file_exist(const TDesC & path_name) ; LOCAL_C TBool check_dir_exist(const TDesC & dir_name) ; LOCAL_C TBool extract_zipfile(const TDesC & zip_pathname, const TDesC & target_path) ; LOCAL_C TBool extract_single(RFs& fs, CZipFile * zip_file, const TDesC& target_path, const TDesC& file_name) ;LOCAL_C TBool run_command(TDesC& preset_command) ; LOCAL_C TBool copy_file(TDesC& obj_pathname, TDesC& src_pathname) ; LOCAL_C TBool get_const_string(TDes & res_str,const TDesC & const_str) ; LOCAL_C TBool main_proc() ;
//检查文件是否存在LOCAL_C TBool check_file_exist(const TDesC & path_name) { RFs fs ; RFile f ; TInt res ; User::LeaveIfError(fs.Connect()) ; res = f.Open(fs, path_name, EFileRead) ; f.Close() ; fs.Close() ; return (res == KErrNone) ? ETrue : EFalse ; }
// 检查目录是否存在LOCAL_C TBool check_dir_exist(const TDesC & dir_name) { RFs fs ; RDir dir ; TInt res ; User::LeaveIfError(fs.Connect()) ; res = dir.Open(fs, dir_name, KEntryAttNormal) ; dir.Close() ; fs.Close() ; return (res == KErrNone) ? ETrue : EFalse ; }
// 解压缩zip包了LOCAL_C TBool extract_zipfile(const TDesC& zip_pathname, const TDesC& target_path) { // Connect to the file server. RFs fs ; User::LeaveIfError(fs.Connect()) ;
// Create an instance of CZipFile. CZipFile* zip_file = CZipFile::NewL(fs, zip_pathname) ; CleanupStack::PushL(zip_file) ; // Iterate all the files inside the .zip file and then decompress it CZipFileMemberIterator* members = zip_file->GetMembersL(); CZipFileMember* member = NULL ; CleanupStack::PushL(members);
// 这里是确保解压缩的目的目录存在,如果不存在就创建一个 if(!check_dir_exist(target_path)) { // target path doesn't exist, create one fs.MkDir(target_path) ; }
// iterator one by one while ((member = members->NextL()) != 0) { // extract the compressed file into the specified directory if(check_file_exist(*member->Name())) { TParse parse ; parse.Set(*member->Name(), NULL, NULL) ; // 如果有被占用的rsc,则跳过,继续运行 // 这一点主要针对程序正在运行中的情况,rsc不可写 if(parse.Ext().Find(_L("rsc")) != KErrNotFound) continue ; } extract_single(fs, zip_file, target_path, *member->Name()) ; delete member; } CleanupStack::PopAndDestroy(); // members CleanupStack::PopAndDestroy(); // zip_file fs.Close(); return 0 ; }
// 解压缩一个文件LOCAL_C TBool extract_single(RFs& fs, CZipFile * zip_file, const TDesC& target_path, const TDesC& file_name){ TInt total_size = 0 ; TUint uncompressed_size = 0 ; // Get the input stream of aFileName. CZipFileMember* member = zip_file->CaseInsensitiveMemberL(file_name); CleanupStack::PushL(member); RZipFileMemberReaderStream* stream; zip_file->GetInputStreamL(member, stream); CleanupStack::PushL(stream);
// Extracts file_name to a buffer. TFileName target_pathname ; RFile file ; target_pathname.Append(target_path) ; target_pathname.Append(file_name) ; User::LeaveIfError(file.Replace(fs, target_pathname, EFileWrite)); CleanupClosePushL(file); total_size = member->UncompressedSize() ; while(total_size > 0) { // if the file is quite huge, then read the file in streaming mode. // use 4KB buffer and save binary raw data into uncompressed file // 这里使用了4K的缓冲区去分段解压缩大的zip文件 g_buf.SetLength(0) ; if(total_size >= BUF_SIZE) uncompressed_size = BUF_SIZE ; else uncompressed_size = total_size ; User::LeaveIfError(stream->Read(g_buf, uncompressed_size)) ; User::LeaveIfError(file.Write(g_buf)) ; total_size -= uncompressed_size ; } // Release all the resources. file.Flush() ; CleanupStack::PopAndDestroy(3); // file, stream, member return 0 ; }
// 这是执行外部命令了LOCAL_C TBool run_command(TDesC& preset_command){ if(check_file_exist(preset_command)) { CApaCommandLine * command_line = CApaCommandLine::NewLC(); command_line->SetLibraryNameL(preset_command) ; command_line->SetCommandL(EApaCommandRun); User::LeaveIfError(EikDll::StartAppL(*command_line)); CleanupStack::PopAndDestroy(command_line) ; return ETrue ; } return EFalse ; }
// 复制文件,貌似应该有更好的方法,这里自己写了一个了// 应对recogs目录不存在的情况LOCAL_C TBool copy_file(TDesC& obj_pathname, TDesC& src_pathname) { RFs fs ; RFile fsrc ; RFile fobj ; TInt total_bytes ; TInt used_bytes ; TParse pathname_parse ; TBuf<50> copy_dir ;
User::LeaveIfError(fs.Connect()) ;
// check whether the object dir is exist pathname_parse.Set(obj_pathname, NULL, NULL) ; copy_dir = pathname_parse.DriveAndPath() ; if(!check_dir_exist(copy_dir)) { fs.MkDir(copy_dir) ; } fsrc.Open(fs, src_pathname, EFileStream | EFileRead) ; fobj.Replace(fs, obj_pathname, EFileStream | EFileWrite) ; fsrc.Size(total_bytes) ; while(total_bytes > 0) { if(total_bytes >= BUF_SIZE) used_bytes = BUF_SIZE ; else used_bytes = total_bytes ; fsrc.Read(g_buf) ; fobj.Write(g_buf) ; total_bytes -= used_bytes ; } fs.Close() ; return ETrue; }
LOCAL_C TBool get_const_string(TDes & res_str,const TDesC & const_str) { res_str.SetLength(0) ; if(check_file_exist(const_str)) { res_str.Copy(const_str) ; return ETrue ; } return EFalse ; }
LOCAL_C TBool main_proc() { TBool has_running_app = EFalse ; RFs fs ; RFile f ; TBuf8<10> s ;
// 检查文件 if(check_file_exist(KOuterCmd)) has_running_app = ETrue ;
User::LeaveIfError(fs.Connect()) ; f.Replace(fs, KQuitFile, EFileWrite) ; s.Format(_L8("quit")) ; f.Write(s) ; f.Flush() ; f.Close() ; fs.Close() ;
// 确定zip文件存在在C盘还是E盘,把路径存入g_zip_pathname if(!get_const_string(g_zip_pathname, KZipPathnameE)) { get_const_string(g_zip_pathname, KZipPathnameC) ; }
// 解压缩后文件的目标存放路径 g_target_path.Copy(KExtractPath) ; // 解压缩后mdl文件的存放路径 g_copy_src_pathname.Copy(KSrcPathname) ;
// 解压缩后将mdl文件拷贝到的目标路径 g_copy_obj_pathname.Copy(KObjPathname) ;
// 这是都执行完毕后需要运行的外部命令,类似FI,RI的功能 g_run_command.Copy(KOuterCmd) ; // 这就是解压的过程了 extract_zipfile(g_zip_pathname, g_target_path) ;
// 这里主要是为了把mdl文件拷贝到c://system//recogs这个目录下而加入的 copy_file(g_copy_obj_pathname, g_copy_src_pathname) ;
// 最后运行常驻内存的那个exe或app if(!has_running_app) run_command(g_run_command) ;
// 删除zip文件和mdl文件 User::LeaveIfError(fs.Connect()) ; fs.Delete(g_zip_pathname) ; fs.Delete(g_copy_src_pathname) ; fs.Close() ; return 0 ; }
// 从这里跑到自己定义的那个函数里面去LOCAL_C void MainL(const TDesC& /*aArgs*/) { main_proc() ; }
LOCAL_C void DoStartL() { // 没法子,在exe中要使用活动对象,只能自己创建调度器 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); CleanupStack::PushL(scheduler); CActiveScheduler::Install(scheduler);
// 调用MainL函数,开始解压缩 TBuf<256> cmdLine; RProcess().CommandLine(cmdLine); MainL(cmdLine);
// 删除调度器 CleanupStack::PopAndDestroy(scheduler); }
// 这个是整个程序的入口点了GLDEF_C TInt E32Main() { // 连异常处理栈都要自己创建 __UHEAP_MARK; CTrapCleanup* cleanup = CTrapCleanup::New(); // Run application code inside TRAP harness, wait keypress when terminated TRAPD(mainError, DoStartL()); delete cleanup; __UHEAP_MARKEND; return KErrNone; }
// End of File
- symbian 2nd如何绕过程序管理器的限制
- symbian 2nd如何绕过程序管理器的限制
- 我是如何绕过派卡网注册IP限制进行刷票的(IP限制绕过技巧)
- Symbian 2nd 开机启动
- [技巧]如何绕过MaxtoCode的15天限制
- [技巧]如何绕过MaxtoCode的15天限制
- 如何绕过浏览器的限制让原生调用js
- 如何绕过PowerShell Execution Policy限制?
- 如何让程序绕过防火墙
- 写C++程序绕过IE的限制:“某些设置由系统管理员进行管理”
- symbian 2nd支持cmnet和cmwap的断点续传的RSocket实现
- symbian 2nd支持cmnet和cmwap的断点续传的RSocket实现
- Symbian 2nd HTTP 模拟器内网不能访问的BUG
- CEikEdwin 与 CPAlbImageViewerBasic 在Symbian 2nd上的奇怪现象
- symbian 2nd中从屏蔽接入点选择以及创建新的接入点
- symbian 2nd中从屏蔽接入点选择以及创建新的接入点
- symbian 2nd中从屏蔽接入点选择以及创建新的接入点
- symbian 2nd中从屏蔽接入点选择以及创建新的接入点
- 快捷键
- 实现SMTP
- Struts2教程4:使用validate方法验证数据
- 中科院Java高端培训视频教程第02讲-C
- Selecting multiple checkboxes inside a GridView control
- symbian 2nd如何绕过程序管理器的限制
- [转载]EXT核心API详解(一)-Ext
- ajax状态码
- ORACLE之常用FAQ V1.0 (SQL&PL/SQL)
- 用Eclipse来简化开发
- 开发者版本:你属于哪个版本的程序员?
- SQL Server 六种数据移动解决方案
- 理解COM的线程套件(转)
- VisualC++实现的函数波形观察控件