Chinaunix首页 | 论坛 | 博客
  • 博客访问: 656655
  • 博文数量: 134
  • 博客积分: 3158
  • 博客等级: 中校
  • 技术积分: 1617
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-30 22:36
文章分类

全部博文(134)

文章存档

2012年(2)

2011年(28)

2010年(68)

2009年(35)

2008年(1)

我的朋友

分类: 嵌入式

2011-04-01 09:00:07

这是我在做wince6的时候为设置自启动而寻找的方法。我发现公司定的这个设备在“Program Files”和windows文件夹下放置的东西在机子重启之后就什么都没有了。我只有使用注册表测试,发现重启后还存在,因此我用注册表方式设置了自启动。而在这个过程中,我发现如果程序放在SD卡内是不行的,只有放在nand才行。为什么放在SD卡内不可以自启动,原因在我下面搜集的几篇文章中找到了,原来SD卡是在自启动程序之后才加载了驱动运行起来的。

 

 

 

wince 自动启动程序设置

修改注册表[HKEY_LOCAL_MACHINE\init]
“Launch80=”app.exe”
“Depend80=hex:14,00,1e,00

这个是设定启动顺序,launch后面的数字越大的越是后启动Depend80后面的指定依赖项,为16进制,上面的语句表明依赖项为launch20 定义的device.exelaunch30中定义的gwes.exe 注意Launch后面的数字范围为099

 

如何让应用程序随wince操作系统自启动

    如何让应用程序随wince操作系统自启动呢?我搜索了一下,网上有不少方法,但有时也会有疏漏的地方,通常一点小小的错误也会导致整个环节不能进行下去。在此,我想跟大家共同探讨一下,欢迎大家指正。

首先,假设你的应用程序为:MyApp.exe

方法一:主要思想:将应用程序及其快捷方式也添加到映像里,再将快捷方式添加到StartUp目录下,这样当系统运行后应用程序就能自动运行。

步骤:

1先保证原工程文件是可以编译成功的。假设编译好的nk.bin文件所在文件夹为xxx_Relase

2创建快捷方式文件MyApp.lnk,文件内容如下:

10#”\Windows\MyApp.exe”(注意引号)

3pb中修改project.bib文件,在FILES Section添加:

MyApp.exe    $(_FLATRELEASEDIR)\MyApp.exe NK H

MyApp.lnk    $(_FLATRELEASEDIR)\MyApp.lnk   NK H

(注:$(_FLATRELEASEDIR)表示xxx_Relase文件夹;NK后面的H表明加入到nk.bin中的文件为隐藏属性)

4 把快捷方式添加到StartUp目录下,具体为:

修改工程的project.dat文件,添加如下内容:

Directory("\Windows\Startup"):-File("MyApp.lnk","\Windows\MyApp.lnk")

5从道理上讲,如果这时把MyApp.exeMyApp.lnk拷贝到xxx_Relase文件夹下,然后Build->MakeImag的话就会把你的应用程序添加到NK里,但实际情况并非如此,经我实验,先要把工程文件全部rebuild一下,我这儿是sysgen了一下,如果你设置了在编译完后MakeImage 的话,会有错误提示你未在你的磁盘上找到MyApp.exe。不用管它。把MyApp.exeMyApp.lnk文件拷贝到xxx_Relase文件夹下,然后MakeImage一下(记住此时千万不能再rebuild了,否则会前功尽弃),把生成的NK.bin烧写到flash里,这样就可以看到你的应用程序MyApp.exe自启动了.

方法二:主要思想:将应用程序添加到映像里,然后用你的应用程序直接替换Wince的桌面程序。

步骤:

1. 像方法一一样把你的应用程序添加到映象里。

    提示:要查看添加映象是否成功,可以在操作系统启动后,看一下windows目录下是否有你的应用程序MyApp.exe(先要设置为可以查看系统文件和隐藏文件)。

2.修改shell.reg(若在pb里找不到,可以到xxx_Relase文件夹下找):

[HKEY_LOCAL_MACHINE\init]

"Launch50"="explorer.exe"

"Depend50"=hex:14,00, 1e,00

把这个explorer.exe改成你的应用程序(比如:MyApp.exe)。

3. MakeImage一下(还是记住不能再build了),把生成的NK.bin烧写到flash里,这样就可以看到你的应用程序MyApp.exe自启动了.

这样做的好处是启动的时候wince的桌面程序都不会启动了,坏处是当你把应用程序关闭的时候由于原wince桌面程序的丢失而会使机器死机。

方法三:主要思想:将应用程序添加到映像里,然后修改注册表,让应用程序自启动。这回不替换wince的桌面程序,而是让wince像加载桌面一样加载你的应用程序,效果跟方法一是一样的。

步骤跟方法二是一样的,只是第二步稍有不同:

shell.reg文件中[HKEY_LOCAL_MACHINE\init]之下添加如下语句:

"Launch80"="MyApp.exe"

"Depend80"=hex:1E,00

说明:"Depend80"=hex:1E,00用来设置启动顺序和依赖程序,若你的应用程序不依赖于其它程序,这句可以不加。

另外,应用程序也不一定就要加载到映象文件里,可以直接从u盘,硬盘,sd卡等加载,但是要先保证你的应用程序自启动时系统已能正确识别挂接的u盘,硬盘,sd卡等。

 

有两个地方启动程序:
1. 在注册表HKLM\Init上加入键值:Launch99="你的程序名(可以是绝对路径)",如果你的程序要依赖别的程序,还要加入:Depend99=依赖程序的启动序号(可以看看Init下其它程序的启动顺序)
2.好像是在HKLM下有个WBT,里面有个地方也可以加入启动程序,每次注销都会重新启动一遍,而Init只有在重新开机时才启动。
你要启动的程序,可以放在你的flash卡上(Init需要加入绝对路径),或者加入bib文件,编译进内核。

 

  WinCE 应用程序开机自启动方法

近日在开发过程中遇到WinCE应用程序开机自动运行的问题,在网上找了找,发现大概有以下三种方法:

 

1 将应用程序和应用程序快捷方式添加到映像里,再将快捷方式添加到StartUp目录下,这样当系统运行后应用程序就能自动运行;

 

2 直接替换WinceSHELL,即修改注册表:

 

[HKEY_LOCAL_MACHINE\init]

"Launch50"="explorer.exe"

"Depend50"=hex:14,00, 1e,00

 

把这个explorer.exe改成你的应用程序(比如:MyApp.exe);

 

3 把应用程序加入到映像,修改注册表:

[HKEY_LOCAL_MACHINE\init]

"Launch80"="MyApp.exe"

"Depend80"=hex:1E,00

 

可以设置启动顺序和依赖程序;

 

以上方法都可行,但是都存在一个问题,就是应用程序是集成到NK里面的,也就是说每次升级应用程序都要重新编译下载内核,很麻烦,尤其在程序调试阶段,大家都希望把应用程序放在SD卡上,这样更新起来比较容易;据说通过第三种方法可以实现,即修改"Launch80"="MyApp.exe""Launch80"="\STDCard\MyApp.exe"( STDCardSD卡目录),但是我试了一下没有成功,因为Launch80运行时SD卡的文件驱动还没有加载,找不到MyApp.exe文件。同样,采用快捷方式加载SD卡里的应用程序也不可行。

所以我采用了另一种方法,自己编了一个小程序,比如叫ShellExe.exe,将此程序加入到映像里,通过StartUp快捷方式调用ShellExeShellExe再去调用SD卡里的应用程序,具体实现步骤如下:

1 eVC下编译如下代码:

int WINAPI WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPTSTR    lpCmdLine,

int       nCmdShow)

{

WIN32_FIND_DATA fd;

HANDLE hd=INVALID_HANDLE_VALUE;

int iCount = 20;

while(iCount--)

{

hd=::FindFirstFile(lpCmdLine,&fd);

Sleep(500);

if(INVALID_HANDLE_VALUE!=hd) break;

}

if(0==iCount) return 0;

FindClose(hd);

SHELLEXECUTEINFO ShExeInfo={0};

ShExeInfo.cbSize=sizeof(SHELLEXECUTEINFO);

ShExeInfo.fMask=SEE_MASK_NOCLOSEPROCESS;

ShExeInfo.hwnd=NULL;

ShExeInfo.lpVerb=NULL;

ShExeInfo.lpFile=lpCmdLine;

ShExeInfo.lpParameters=L"";

ShExeInfo.lpDirectory=NULL;

ShExeInfo.nShow=SW_SHOW;

ShExeInfo.hInstApp=NULL;

ShellExecuteEx(&ShExeInfo);

return 0;

}

  生成ShellExe.exe的可执行文件,此段代码主要功能是查找指定的应用程序,然后执行;下面这段代码可以保证在SD卡文件系统正确加载后才去执行应用程序;

while(iCount--)

{

hd=::FindFirstFile(lpCmdLine,&fd);

Sleep(500);

if(INVALID_HANDLE_VALUE!=hd) break;

}

文件的名称和路径由命令行参数指定:

ShExeInfo.lpFile=lpCmdLine;2 新建一个快捷方式,如Autorun.lnk,按如下方式编辑其内容:

 

21#\windows\shellexe.exe \stdcard\MyApp.exe其中\stdcard\MyApp.exe应用程序的绝对路径;

 

3 MyApp.exeAutorun.lnk添加到NK里,方法是在project.bib文件内加入如下内容:

 

ShellExe.exe f:\WINCE420\PBWORKSPACES\LioetEnTer\RelDir\ShellExe.exe NK S

Autorun.lnk f:\WINCE420\PBWORKSPACES\LioetEnTer\RelDir\Autorun.lnk NK S注意:ShellExe.exe的属性不能带H(隐藏).

 

4 project.dat里加入如下内容:

 

Directory("\Windows\Startup"):-File("Autorun.lnk","\Windows\Autorun.lnk")5 选择Make Image生成映像(当然Build也可以,就是慢点儿),烧到FLASH里,开机运行,可以看到SD卡里的MyApp.exe被正确执行。

 

总结

  这种方法用起来比较方便,ShellExe.exe不用每次都重新编译,只要根据应用程序路径修改Autorun.lnk即可,可以加载FlashU盘、SD卡里的应用程序。调试及升级应用程序就不用重新烧写内核了。

 

WinCE自启动Shell的问题

WinCE开机即运行定制的Shell是很多系统的基本要求,有时还需要屏蔽WinCE自带的ShellWinCE中程序的自启动,一般有两个实现方法,修改注册表和添加自启动快捷方式。修改注册表比较方便,如下:

 

       [HKEY_LOCAL_MACHINE\init]

         "Launch70"="MyApp.exe"

         "Depend70"=hex:14,00,1e,00

 

      只要将MyApp.exe打包到NK,并在platform.reg中加入上面的注册表信息,这样WinCE启动时便会自动运行该程序。但这时WinCE自带的Shell总是先出来,然后才运行MyApp.exe,为了避免这种情况,我们可以将注册表设置修改如下:

 

       [HKEY_LOCAL_MACHINE\init]

         "Launch50"="MyApp.exe"

         "Depend50"=hex:14,00,1e,00

 

      即将原来启动explorer.exe的值换为MyApp.exe。这样WinCE启动时直接进入定制的Shell,而不启动explorer.exe。但这时有可能引入了新问题,如果定制的Shell是基于MFC编写的,并且其中用到了如CFileDialog等类库时,就会出现意想不到的情况,如下图所示:

 

上图是在不启动Explorer.exe时,尝试导入注册表文件出现的状况截图,而在启动explorer.exe时是没有问题的。这说明CFileDialog在某种程度上依赖于explorer.exe,具体细节没研究。但说明不启动explorer.exe,基于MFCShell运行时就可能会出问题。所以explorer.exe必须启动,但又不能出现WinCE界面。要解决这个问题自然就想到修改explorer.exe了。WinCE5.0WinCE6.0中,这一部分的代码都是公开的,在WinCE6.0Shell的相关代码在C:\WINCE600\PUBLIC\SHELL\OAK\HPC\EXPLORER\MAIN目录下。

 

       大致看了一下这一部分的代码,发现只需修改如下两个文件,就应该能实现需求。

 

       C:\WINCE600\PUBLIC\SHELL\OAK\HPC\EXPLORER\MAIN\desktop.cpp

 

+ expand sourceview plaincopy to clipboardprint?

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

bool CDesktopWnd::Create()  

{  

 

    IShellFolder    *pSHF;  

    FOLDERSETTINGS fs;  

    RECT rc;  

    HRESULT hr = E_FAIL;  

      

    // Get a shell folder for the desktop  

    hr = SHGetDesktopFolder(&pSHF);  

    if(hr || !pSHF)  

        goto Cleanup;  

 

    // create a shell view for it  

    hr = pSHF->CreateViewObject(NULL, IID_IShellView, (LPVOID *)&_psv);  

    if(hr || !_psv)  

        goto Cleanup;  

 

    fs.ViewMode = FVM_ICON;  

    fs.fFlags = FWF_DESKTOP | FWF_ALIGNLEFT | FWF_NOSCROLL;  

 

    //++changed by hjb  

    //Desktop的窗口大小设为0  

    //SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN));  

    SetRect(&rc, 0, 0, 0, 0);  

        //--changed by hjb  

      

    // create the desktop's view window (no need to AddRef since CreateViewWindow does it)  

    hr = _psv->CreateViewWindow(NULL,  &fs, (IShellBrowser *)this, &rc, &_hWnd);  

    if(hr || !_hWnd)  

    {  

        Release();  

        goto Cleanup;  

    }  

 

    RegisterDesktop(_hWnd);  

 

Cleanup:  

    if(pSHF)  

        pSHF->Release();  

 

   return (hr == S_OK);      

} 

bool CDesktopWnd::Create()

{

 

    IShellFolder    *pSHF;

    FOLDERSETTINGS fs;

    RECT rc;

    HRESULT hr = E_FAIL;

   

    // Get a shell folder for the desktop

    hr = SHGetDesktopFolder(&pSHF);

    if(hr || !pSHF)

        goto Cleanup;

 

    // create a shell view for it

    hr = pSHF->CreateViewObject(NULL, IID_IShellView, (LPVOID *)&_psv);

    if(hr || !_psv)

        goto Cleanup;

 

    fs.ViewMode = FVM_ICON;

    fs.fFlags = FWF_DESKTOP | FWF_ALIGNLEFT | FWF_NOSCROLL;

 

    //++changed by hjb

    //Desktop的窗口大小设为0

    //SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN));

    SetRect(&rc, 0, 0, 0, 0);

        //--changed by hjb

   

    // create the desktop's view window (no need to AddRef since CreateViewWindow does it)

    hr = _psv->CreateViewWindow(NULL,  &fs, (IShellBrowser *)this, &rc, &_hWnd);

    if(hr || !_hWnd)

    {

        Release();

        goto Cleanup;

    }

 

    RegisterDesktop(_hWnd);

 

Cleanup:

    if(pSHF)

        pSHF->Release();

 

   return (hr == S_OK);   

}

 

       C:\WINCE600\PUBLIC\SHELL\OAK\HPC\EXPLORER\MAIN\explorer.cpp

 

+ expand sourceview plaincopy to clipboardprint?

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

DWORD WINAPI CreateTaskBar(LPVOID pEvent)  

{  

    HANDLE hSyncEvent = *((HANDLE *) pEvent);  

    CTaskBar *pTaskBar = NULL;  

    HWND hwndTB = NULL;  

      

    pTaskBar = new CTaskBar;  

      

    //++added by hjb  

    //在创建任务栏时强制终止  

    if(pTaskBar)  

    {  

        delete pTaskBar;  

        SetEvent(hSyncEvent);  

        return 0;  

    }  

    //--added by hjb  

       

    if(!pTaskBar)  

    {  

        SetEvent(hSyncEvent);  

        return 0;  

    }  

 

    g_TaskBar = pTaskBar;  

    if(!pTaskBar->Register(g_hInstance))  

    {  

        g_TaskBar = NULL;  

        delete pTaskBar;  

        SetEvent(hSyncEvent);  

        return 0;  

    }  

 

    RegisterTaskBar(pTaskBar->GetWindow());  

    SetEvent(hSyncEvent);  

 

    DWORD dwRet = pTaskBar->MessageLoop();  

 

    delete pTaskBar;  

 

    return dwRet;  

} 

DWORD WINAPI CreateTaskBar(LPVOID pEvent)

{

    HANDLE hSyncEvent = *((HANDLE *) pEvent);

    CTaskBar *pTaskBar = NULL;

    HWND hwndTB = NULL;

   

    pTaskBar = new CTaskBar;

   

    //++added by hjb

    //在创建任务栏时强制终止

    if(pTaskBar)

    {

        delete pTaskBar;

        SetEvent(hSyncEvent);

        return 0;

    }

    //--added by hjb

   

    if(!pTaskBar)

    {

        SetEvent(hSyncEvent);

        return 0;

    }

 

    g_TaskBar = pTaskBar;

    if(!pTaskBar->Register(g_hInstance))

    {

        g_TaskBar = NULL;

        delete pTaskBar;

        SetEvent(hSyncEvent);

        return 0;

    }

 

    RegisterTaskBar(pTaskBar->GetWindow());

    SetEvent(hSyncEvent);

 

    DWORD dwRet = pTaskBar->MessageLoop();

 

    delete pTaskBar;

 

    return dwRet;

}

 

修改完这两处后,先编译该目录,然后再重新编译整个系统(执行Sysgen)应该就可以了。Explorer.exe依然启动,依然可以听到WinCE启动的声音,但WinCE的界面已经屏蔽掉了。此时,基于MFCShell也能正常工作,如下图所示: 

 

 

      在实际操作时,我没有通过修改源代码编译来完成这个测试。因为在编译C:\WINCE600\PUBLIC\SHELL\OAK\HPC\EXPLORER\MAIN目录时,发现它只生成了explorer.lib。考虑到重新编译整个系统的时间太长,所以直接修改了工程目录下的explorer.exe的文件,MakeImg后测试的。这里应该有快速编译的方法,但目前不知怎么弄。

 

      修改后,在WinCE6.0的模拟器中测试,达到了预想的效果。这样就大概解决了基于MFCShellExplorer.exe之间的矛盾,是不是有隐患还不清楚,目前看来没问题。

 

另外需要注意,修改publicprivate目录下的文件时,一定先做好备份,以免后患。          

      修改后的WinCE6.0explorer.exe及演示视频的下载地址:

 

       http://files.cnblogs.com/we-hjb/WinCE_Shell.rar

 

引用网址:http://www.cnblogs.com/we-hjb/archive/2008/12/28/1364070.html

 

 

HKEY_LOCAL_MACHINE\init\Launch80="\nandflash\em9161_xwj.exe"

 

[PB操作使用技巧]WinCE下直接启动应用程序的方法

其实让一个程序在wince里启动和windows里差不多,直接设置其为启动项,这个有几个方法。一个就是制作一个快捷方式,指向我们的应用程序如app.exe,然后将快捷方式放到\windows\startup下面。

    步骤如下:(假设app.exe已经拷贝到windows下面)

    1 pb中创建一个文件,文件类型选txt,然后命名为.lnk后缀,假设名字为test.lnk

    2 编辑其内容为: 16#\windows\app.exe。备注:前面的16# 后面所有字符的总和,包括空格。Wince的帮助文档上说这么定义就行,但是我尝试后,最后down到目标机上面时提示找不到文件,在wince里查看这么创建的test.lnk的属性,发现其指向\windows\app.exe后面还有两个方框,因此不对,我的解决方法是修改test.lnk的内容为16#"\Windows\app.exe"

    3 编辑好lnk文件内容后在pb中修改project.bib。在files段后面添加下面一行:(和添加别的文件到image中类似,见我的《WinCE中如何向image中添加文件》,也要在pbflatform菜单的setting下添加build语句,不再赘述)

        test.lnk $(_FLATRELEASEDIR)\test.lnk NK S

    project.dat中增加下面一行:

         Directory("\Windows\startup"):-File("test.lnk","\Windows\test.lnk")

    这样后系统启动后就会自动启动我们的程序了。

   

    另外一种方法是编辑注册表:在project.reg中添加如下内容

        [HKEY_LOCAL_MACHINE\init]

        "Launch80"="app.exe"

        "Depend80"=hex:14,00,1e,00

    这个是设定启动顺序,launch后面的数字越大的越是后启动,Depend80后面的指定依赖项,为16进制,上面的语句表明依赖项为launch20定义的device.exelaunch30中定义的gwes.exe 注意Launch后面的数字范围为099 ,此范围之外的将不会有效果。

    这样两种方法的效果都是系统都是系统先启动资源管理器explorer.exe(就是看到的默认桌面),然后启动我们的程序,(如果利用taskman shell然后去掉任务栏那么效果更好)但是这样还不够,我们如何不显示桌面,直接显示我们的程序呢?

    网上有人介绍的方法是去掉standard shell,但是我编译总是报错。我采用的方法是替换注册表中lauch50中的explorer.exe为我的app.exe,即搞定。

    修改注册表的方法:先把带KITL的系统跑起来,在PBTOOLS->Remote registry editor里修改,验证有效后,再去修改platfrom.reg, 或者自己写个REG文件,然后在platform.regINCLUDE进来 SYSGEN后确认PBWORKSPACE里相关项目的REL目录里reginit.ini文件里包含了自己做的修改后make image然后DOWNLOAD下去就OK了。

    值得补充的是,我们前面介绍的步骤中那个修改平台setting,添加语句的,是因为我每次都是重新sysgenbuild,如果只是简单的make image的话(都是pb中的build OS菜单下的命令),那么将直接用release中的内容,因此也可以直接将文件放到release文件夹,然后改project.bib等实现往image中添加文件。 同样,也可以直接修改release中的shell.reg中的launch50值为我们自己的程序(或者类似修改reginit.ini文件,reginit.ini文件存放有所有wince的静态注册表,来达到去掉桌面,直接启动我们程序的效果)。

注意,这么启动的程序,如果点击关闭,就会死机的,因为没有窗口运行了。实际运用中,当然不会让用户关闭我们的程序,除非他一起关闭系统。

如果也需要build的话,可以通过往image中添加文件的方法将我们改好的shell.reg添加到release目录

阅读(22246) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~