返回首页

简介
如果计划获得Windows Vista的认证标志。NET应用程序,这篇文章对您有用。在这里,你会发现一个简单但完整(可验证)VB.NET C#的桌面应用程序,包括完整的源代码的应用程序和在Visual Studio 2005解决方案的安装,所有包装,。背景
前段时间,我被分配与艰巨的任务,似乎对我:获得Windows Vista的认证标志为我们的应用程序之一。我实现这一应用程序的源代码,Visual Studio中,和互联网连接。好了,和必要的资金需要。
这项工作已经完成,现在认证的应用程序。虽然"dauntingquot;实际上并没有合适的词来形容这个过程,这是很不容易的。问题是缺乏由微软提供的信息,我不是指所有administratrivia(注册)页,但纯技术的一部分。微软抛出测试用例文档,你的脸... ...运气好,你都不在话下。
例如,测试案例25:验证应用程序妥善处理在使用过程中的安装文件。你开的Orca浏览您有您的应用程序创建和安装...抱歉,没有一丝的MsiRMFilesInUse对话框。与Visual Studio创建的安装程序不创建它。现在怎么办?
幸运的是,我们有互联网,我们的搜索引擎,而我们有不少人已经打了认证过程的几个人。例如,解决的MsiRMFilesInUse问题是。 OK OK,我说,微软并没有提供任何帮助,现在我发布MSDN博客的链接。我的意思是,微软应该摆在首位,这一信息,在一个更​​完整的测试用例文档或在一个单独的FAQ,。
好了,足够的微软好/恶的讨论。事实是,在我完成了认证工作,我认为,这将是一个好主意,分享知识,我在整个过程中为了使生活具有相同任务的其他人更容易获得。谁知道呢,也许quot; youquot;可以节省quot; myquot生活的明天,所以我希望你能然后我高兴。在你去未来
首先,我假设你已经得到你的脚与认证过程中。我的意思是,我想,大家都知道,为了获得认证,应用程序必须通过测试用例的数量,由微软(下载从,它规定的情况下测试文件中所述,并,一旦你的应用程序准备好了,你需要提交给一个权威机构检测,除测试的情况下,我无法解释的整个过程中的细节这里。
其次,我认为您的应用程序是我认证的结构相似。 "在结构上similarquot;是一个很好的流行语,我现在已经发明了说,您的应用程序应该如下:完全托管的应用程序(。NET程序集,没有非托管代码)。32位应用程序。只有一个桌面应用程序的安装。无论是司机或服务安装。独立的应用程序。网络连接是不是必需的。始终是每台机器安装。每个用户安装不支持。应用程序数据是所有用户共同。每个用户的数据是不会产生。应用程序不安装后自动启动。关机后不重新启动该应用程序。不支持并发用户会话。不支持远程桌面(终端服务器)执行。
我会在这里解释,适用于有上述功能的应用程序。这并不是说,如果您的应用程序不同某处从我的,你现在必须停止阅读。它只是说,你必须要格外小心,因为一些的东西,我会在这里说可能无法适用于您和/或你需要额外的信息搜索别处。例如,如果您的应用程序支持并发用户会话,你必须确保没有听说过一个又一个声音从一个会话。这里我不会涵盖这一问题,因为我没有需要解决。闪烁的大红色的字母声明
这是常识,但无论如何,这里有云:不管你读到这里,你必须测试您的应用程序对所有适用的测试情况下,然后提交给权威机构检测。我将不接受任何类型的投诉,"我浪费了一个失败的认证1000美元,因为你说:XXX,但在我的应用程序,它打开了ZZZ quot;!我人类,因此,我犯的错误,更何况我不知道的一切有关Visual Studio和。NET应用程序。我想帮你,但我不是神。所以,我们会怎样做呢?
我们将剖析,我特别为本文创建的应用程序。应用程序的名称是杀手级应用和开发是虚构的公司胶囊公司。源代码,在一个Visual Studio 2005解决方案的形式,可供下载,在此页面顶部。
杀手级应用,从本质上讲,没有什么用处(它包含了几个菜单,显示一些数据,并允许您创建和读取文本文件的父MDI窗体)。但是,它会通过所有的测试案例和可能获得Windows Vista徽标认证,也就是说,如果你是比尔 - 盖茨,并在你的口袋里的1000元注,准备花什么。我已经创建了它,它模仿的实际应用,我准备认证的基本结构。出于这个原因,也有VB.NET和C#项目的混合。
您已经阅读本文后,您可以创建自己的应用程序的骨架使用的杀手级应用解决方案,或者你可以抓住一些源代码片段,或者你可以简单地得到关于如何做的事情一些想法和做所有的代码从头开始;任何最适合您的的需求。它甚至可能发生,你找到一个更好的方式来做事(真的!)。在这种情况下,这将是很好,如果你能落个评论解释你的发现。设定您的环境
让我们开始移动准备需要编译杀手应用程序(而非测试环境:你不需要Windows Vista的发展过程中,事实上,我使用Windows XP)环境。首先,你需要,很明显,Visual Studio 2005中。我想,Visual Studio 2008中也将通过适当的解决方案转换工作。
其次,我将假定您已经得到您的组织的证书。如果没有,你不能够编译的解决方案,除非你修改的解决方案在Visual Studio中生成后事件(后面的更多细节)。我假设的全权证书和私钥文件名,分别capsulecred.spc和capsulekey.pvk,但当然你也可以使用任何你喜欢的名字。
三,创建命名vistatools在您的主驱动器的根目录(即C:\ vistatools)。这是我们将在其中编译应用程序时所需的一些额外的文件。
四,复制在vistatools目录中的下列文件:mt.exe,微软清单工具。这是在Visual Studio 2005 SDK的一部分,你应该在C:\程序文件\微软Visual Studio 8 \ SDK \ V2.0 \ Bin目录。否则,。MsiTran.exe,MSI变换工具。这是的一部分。signtool.exe,代码签名工具。它的Visual Studio 2005 SDK和Windows Vista SDK的一部分。
(当然你可以找到单独下载这些文件在互联网上搜索,但我更喜欢点的quot; officialquot;源。)
第五,你需要创建一个数字证书文件,为您的组织的全权证书文件和私钥文件。你需要做的所有的应用程序只有一次。下面是步骤:下载,解压缩和安装复制capsulecred.spc和capsulekey.pvk文件的vistatools目录。打开命令提示符,进入到vistatools目录并执行以下命令:pvkimprt的PFX capsulecred.spc capsulekey.pvk
鬼就会出现要求私钥的密码。后来,它会问你,如果你要导出的私钥。说是的。在下一个屏幕上选择默认参数(PKCS#12格式,允许安全的保护),并进入一个新生成的证书文件(我假设您输入kaitokun这里)密码。最后,当问的证书文件名,浏览到vistatools目录,​​并选择一个合适的名字(我假设capsulekey.pfx)。
当你完成,你可以从vistatools目录中删除capsulecred.spc和capsulekey.pvk键,如果你想(但确保您储存他们在其他地方,当然!)。该目录的内容应该是:mt.exe,MsiTran.exe,signtool.exe和capsulekey.pfx。这一切,你准备编译杀手级应用。应用程序结构
在这里,我们将采取一个杀手级应用概述:它是什么组成的,它做什么。后来,我们将深入的源代码和项目设置的细节。杀手级应用解决方案包括四个项目:杀手级应用:主应用程序集,它是一个VB.NET的可执行文件包含所有的图形用户界面和应用程序逻辑(非常简单)。KillerApplication.Support:一个C#DLL只包含一个自定义控件。我已经包括它模仿的最真实世界的应用程序的常规结构(一个主要的可执行文件加一个或多个支持DLL文件)。KillerApplication.Install:另一个C#DLL,这其中包含了一个安装程序自定义操作的类。稍后我们会看到为什么这个代码需要在自己的大会。杀手应用程序的安装:安装项目将生成安装程序(MSI)文件杀手级应用。
当你运行应用程序时,你会看到一个MDI窗体包含三个主要条目的菜单。此菜单允许您执行一些简单的动​​作,这将有助于你在行使测试用例(或至少是意图):"文件"菜单包含三个项目:打开将打开表单的控制,使您可以读取并显示一个文本文件的内容放置在磁盘的任何位置。任何异常都将被捕获并显示其信息。有按钮来填充文件的路径文本框中三个quot; interestingquot;地点:Windows目录和个人目录logouser1和logouser2。使用这种形式来行使的测试案例2。除将开放与控制,允许你创建一个文本文件在磁盘的任何位置的一种形式。同样,异常将被捕获并有按钮来填充与Windows,logouser1和logouser2目录的文件路径"文本框中。使用这种形式行使测试用例2和3。出口将 - 你猜对了 - 终止应用程序的执行。做的东西菜单包含五个项目:显示冷却控制将打开一个窗体,仅仅包含支持DLL中定义的自定义控制。查看照片将打开只显示摄影的形式。摄影文件作为包含文件的项目。这种形式,以及以下两种形式,间接行使测试用例15。查看文本查看照片的形式类似,但这个时候,一个文本文件的内容显示,而不是摄影。查看数据工作,只有当您有安装SQL Server 2005 Express的机器上运行的应用程序。作为包含文件的项目包括,在一个小的SQL Server数据库中包含的数据显示,它会打开一个形式。连接字符串有一个很好的技巧,我们后面会看到。碰撞会产生一个空引用异常。这是一个快速的方式行使测试用例32。"帮助"菜单中只包含一个菜单项:关于将显示一个简单的关于对话框。
这就是全部。这不是非常多,但足以行使所有适用的测试用例。现在,让我们的详细信息。设置的解决方案
有三个主要的重点领域,在执行应用程序清扫时,:解决方案/项目设置,源代码和安装程序项目。在本节中,我们将看到的第一个细节。我会做列举,如果要从头开始创建解决方案,应该遵循的步骤。所有这一切,当然,创建的杀手级应用解决方案时,我所做的一切。我相信,这些信息将是对您有用,即使你是准备为一个已经存在的解决方案的认证。
注意,当然,你可以使用你喜欢的任何解决方案和项目的名称,并根据您的需要,创造更多或更少的项目。1。创建项目
打开Visual Studio并创建一个新的项目类型其他项目类型 - GT; Visual Studio解决方案- GT;空白解决方案。将它命名为杀手级应用。三个新项目添加到解决方案:一个VB Windows窗体应用程序命名的杀手级应用,一个C#类库项目名为Capsule.KillerApplication.Support,和另一个C#类库项目名为Capsule.KillerApplication.Install。删除默认的Form1和Class1项目,Visual Studio会将项目默认情况下。不要创建安装程序"项目,在这一刻。新增主要VB.NET项目的支持类库引用。添加一个新类的主要VB.NET项目,并将它命名为计划。以下占位符代码添加到类:

<STAThread()> _

Public Shared Sub Main(ByVal args() As String)

End Sub

打开的属性对话框中的主要VB.NET项目,并在"应用程序"选项卡执行以下变化:更改根命名空间,以Capsule.KillerApplication。取消选中启用应用程序框架中。更改启动对象编程。
注意,如果您的主应用程序项目是一个C#项目,计划类占位符的主要方法是自动创建的。您还需要改变根命名空间的话。您可能会问,"为什么我们费心主要方法,而不是放置在主窗体的Load事件的启动代码quot;?正如我们将看到我们来看看应用程序的源代码时,我们需要检查一些条件,我们的应用程序启动之前,其中一些甚至可以防止运行应用程序。因此,我们需要能够执行代码之前,任何形式的创建。2。设置元数据
现在,我们将一些应用程序中的每一个项目到AssemblyInfo文件的信息填写。在C#项目,它是在"属性"文件夹。在VB.NET项目,它是在我的项目"文件夹中,但在这种情况下,你首先需要激活的显示解决方案资源管理器窗口中的所有文件图标。主应用程序组件,这是我们会设立的数据:{C}
的支持DLL,数据将是:
[assembly: AssemblyTitle("Capsule.KillerApplication.Support")]

[assembly: AssemblyDescription("Support DLL for Killer Application")]

[assembly: AssemblyCompany("Capsule Corporation")]



[assembly: AssemblyProduct("Capsule.KillerApplication.Support")]

[assembly: AssemblyCopyright("漏 Capsule Corporation 2007, 2008")]

...和安装DLL自定义操作非常相似,只是变化大会的标题和描述。设置元数据是绝对必要的,但它是很好的做法。杀手级应用使用这个数据在关于对话​​框。3。添加清单文件(S)
测试用例1指出,所有应用程序的可执行文件必须quot;包含一个嵌入的清单定义其执行level.quot的;随着Visual Studio 2005中,没有直接的方式包括在集会manifest文件。使用Visual Studio 2008使得这一任务变得更加容易,顺便说一下,但我们假设我们都是穷人视觉工作室2005用户这里。幸运的是,以间接的方式做到这一点。在应用程序的主大会(VB.NET可执行),添加一个新的文本文件,这名杀手Application.exe.manifest。文件名必须为程序集名称,加。exe.manifest相同。确保在属性页的文件,生成操作设置为None。然后打开该文件,并粘贴以下内:
<?xml version="1.0" encoding="utf-8" ?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">

    <security>

      <requestedPrivileges>

        <requestedExecutionLevel level="asInvoker" uiAccess="false" />

      </requestedPrivileges>

    </security>

  </trustInfo>

</assembly>

注意,如果我们的应用程序有更多的可执行文件(*. exe)的项目,我们将不得不重复这一步每一个。清单文件的内容始终是相同的,只有文件名本身的变化。这个manifest文件将被处理的项目生成后事件,我们会看到现在。4。安装程序生成后事件
记住vistatools曾几何时我们创建的目录?那么,现在它的时候使用它。我们将设置项目后建立一些不错的东西,使生成的程序集的事件。在VB.NET可执行项目的属性窗口,选择"编译"选项卡,单击"生成事件"按钮,并在生成后事件命令行中粘贴以下:
%HOMEDRIVE%\vistatools\Mt.exe -manifest "$(ProjectDir)$(TargetFileName).manifest"

     -outputresource:"$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName);1"

%HOMEDRIVE%\vistatools\signtool.exe sign

    /f %HOMEDRIVE%\vistatools\capsulekey.pfx /p kaitokun /v

         /t http://timestamp.verisign.com/scripts/timstamp.dll

    "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"

注:实际上,只有两个命令来执行。我划分在各自以提高可读性单独的行。在Visual Studio中生成后事件窗口,命令必须在一个单一的每一行。
在第一个命令,我们使用清单文件嵌入到生成的程序集清单的工具。第二个命令将签署大会,从而实现测试案例5(quot;验证应用程序安装的可执行文件和文件signedquot;)。请注意,您将有改变capsulekey.pfx的文件的名称和您的真实价值kaitokun密码。如果你不还组织证书,但仍然要编译的应用程序,只需删除此行,或者更好,在前面加上一个REM命令禁用它。
注意,我们的目标,而不是在目标生成目录(通常是BIN \ CONFIGNAME)中创建文件$(PROJECTDIR)OBJ \ $(ConfigurationName)目录中创建的文件。这是,因为生成安装程序时,,打包的可执行文件会实际上是从obj目录。这是文件,我们要被quot; manifestedquot;并签署,而不是在开发计算机用于调试和测试使用的,。
现在,让我们一起去的支持组件。对于KillerApplication.Support和KillerApplication.Install,打开属性窗口,选择"生成事件"选项卡,在生成后事件命令行中,粘贴以下(请再次注意,它是一个单一的命令,分为四线):
%HOMEDRIVE%\vistatools\signtool.exe sign /f

    %HOMEDRIVE%\vistatools\capsulekey.pfx /p kaitokun /v

    /t http://timestamp.verisign.com/scripts/timstamp.dll

    "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"

是的,这是完全相同的可执行文件的情况下,但没有明显的东西。同样,如果你还没有一个组织证书,删除或注释命令暂时。必须设置在所有项目中,生成一个EXE文件生成后事件(两个命令)的第一个版本。第二个版本(一个命令)必须设置上的所有项目生成一个DLL文件。5。添加你的代码和数据
这就是所有你需要有关的项目设置(除了安装项目,稍后我们将剖析)。现在,你需要添加的应用程序代码和辅助数据(图片,文字,数据集,无论)的项目。您可以使用任何代码和数据,您需要... ...除外,当然,你需要做一些特殊的事情,因为我们现在看到的。我的数据在哪里?
在我们投身到源代码的复杂性,我们将采取看,还需要注意的另一个问题:应用程序的数据。也就是说,所有应用程序文件,是该项目的一部分,但没有代码。
Visual Studio中允许你添加这些类型的文件到您的项目。只需右键单击该项目并选择添加新的项目,或加入现有项目。然后在属性页的项目,确保生成操作设置为内容。杀手级应用,这里面的主要项目的数据文件夹的三个文件:一个摄影,一个文本文件和一个数据库文件,如下图所示:{S1}
问题是:这些文件的应用程序时产生?答案是,它取决于你如何生成应用程序:如果直接建设或运行的应用程序从Visual Studio内,将复制的内容文件在同一目录中生成的可执行文件(即项目目录的bin \ CONFIGNAME目录)。当创建一个安装程序,我们将在后面看到,你可以指示编译器完全收拾所有内容的文件,在安装时,复制他们在目标计算机上任何您所选择的的目录。
在这两种情况下,原来的目录结构保存。这意味着,在杀手级应用的情况下,生成解决方案时将有一个bin \发布\杀手Application.exe文件连同一个bin \发布\ DATA \文本\ Agreement.txt,以及两个文件(照片和数据库),在其原有的相对路径:{S2}
现在的时刻,采取一看测试用例15:quot;验证应用程序安装default.quot正确的文件夹,应用程序范围内的数据,正确的文件夹是一个%ALLUSERSPROFILE%变量指出(也称为CommonApplicationData和CommonAppDataFolder。NETesque)。这通常是C:\ Documents和Settings \所有用户在Windows XP和C:\ ProgramData Windows Vista中。如果你骗了一点,向下滚动(或更好,看到的杀手级应用解决方案),你会看到的杀手级应用安装创建一个目录,名为,当然,杀手级应用,并把所有的项目内容文件:{S3}
因此,考虑到这一点,你可能认为,这将是很好使用单一的代码库上所有情况下,无论数据被放置访问应用程序数据。你是正确的。这里是我是如何实现的杀手级应用:创建名为Program类使用DataDirectory的一个静态字符串变量。在启动时,检查是否有一个名为应用程序的可执行目录中的数据目录。如果是这样,这个目录的路径设置使用DataDirectory。否则,将使用DataDirectory%ALLUSERSPROFILE%\"杀手级应用"\数据。当你需要从代码内访问应用程序数据,获得正确的路径,文件的相对路径相结合的Program.DataDirectory价值,没有数据的一部分。例如:Path.Combine(Program.DataDirectory,"文件"\ Agreement.txtquot)。
这里额外的技巧,但我们会看到他们在查看源代码时。源代码(最后)
我们现在真的准备好了,看的杀手级应用的源代码。我们将着眼于引导顺序,然后我们会看到什么上的杀手级应用的主窗口的菜单项,最后我们将探讨在安装程序支持的项目中包含的自定义操作。让我们启动
我们将启动引导顺序的源代码清扫,就是杀手级应用在启动时执行的代码。在Visual Studio中打开Program.cs文件,研究为主要方法,在这里你会发现什么:1。环绕主要在一个try - catch日志块
,您可能会收到惊讶,当你看到,主要方法如下:
<STAThread()> _

Public Shared Sub Main(ByVal args() As String)

    Try

        _Main(args)

    Catch ex As Exception

        Dim text As String = _

            String.Format("Unexpected exception in Killer Application:{0}({1}){0}{2}", _

            Environment.NewLine, ex.GetType().Name, ex.Message)

        EventLog.WriteEntry("Application Error", text, EventLogEntryType.Error, 1000)

        Throw

    End Try

End Sub

测试用例32说:"验证该应用程序只处理已知和expected.quot例外,那么,为什么我们所做的正好相反呢?我们不应该只是让单独的意外异常?
问题是什么,你可以阅读的quot; verificationquo​​t;部分测试用例:quot;必须列为应用程序错误"源"和"源"信息作为Windows中列出的消息的错误消息错误报告每个可执行文件,上面为了通过这个测试case.quot,它发生,生成的信息消息,但有没有一丝的事件日志中的错误信息。因此,我们必须手工生成,而这正是这个怪异的代码。日志记录完成后,throw语句重新抛出异常未修改,所以一切都OK,我们通过测试案例。
注意在catch块的结束,我们必须使用抛不抛出前。前者将重新抛出原始的异常与原来的通话保留堆栈,而后来会产生一个新的异常会导致调用堆栈丢失(也会导致测试案例32失败,我承认我不知道为什么) 。
初始化代码的其余部分是里面的_main方法。2。设置未处理的异常模式
在做别的事情之前,下面的一段代码是必需的:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)

没有这一点,你会收到这丑陋的错误窗口,而不是看中WER窗口未处理的异常的情况下:{S4}的
,你猜对了,测试案例32将失败,如果发生这种情况。3。检查远程桌面执行
9测试用例说:quot;验证应用程序启动和执行正确使用远程Desktop.quot的,但正如我刚才解释,杀手级应用不支持远程桌面执行。可以通过测试的情况下如何呢?答案是小字。注意有一个测试用例中描述说:quot;如果应用程序不支持远程桌面,必须弹出一个消息,表明用户和消息写入Windows NT事件日志,以通过此测试case.quot;这里是我们的生命得到保存:
If SystemInformation.TerminalServerSession OrElse _

        Command.ToLower().Contains("failremote") Then

    MessageBox.Show("Terminal Server execution is not allowed.", _

        "Killer Application", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)

    Dim evlog As New EventLog_

        ("Application", Environment.MachineName, "Killer Application")

    evlog.WriteEntry("Terminal Server execution was attempted. _

            User was notified and application terminated.", _

         EventLogEntryType.Information)

    Return

End If

failremote命令行开关是我使用此功能的行使,而不必实际设立一个终端服务器连接的一招。它在实际应用中可以去掉。顺便说一下,这段代码幸得。4。检查现有的应用程序实例
测试用例8说:quot;验证应用程序启动和执行正确使用快速用户Switching.quot;再次,这是杀手级应用不支持的功能。再次,小字为我们节省了:quot;如果应用程序不支持并发用户会话,它必须弹出了一个消息,表明这个用户,并写入到Windows NT事件日志消息,为了通过这个测试案例。 quot;
,所以我们会做一些类似的远程桌面执行的情况下,却多了几分复杂。我们首先会检查是否已经被另一个用户运行的杀手级应用,如果这样,我们显示一个错误信息,我们创建相应的事件日志,和我们终止。如果没有,我们检查是否已经被自己运行的杀手级应用;若有,我们激活的实例已在运行的主要窗口。
我们需要一个小的quot; advancedquot;代码实现这一目标。在支持项目,你可以找到AlreadyRunningChecker类(应该在主体工程,但我在C#代码,我是懒得把它转换到VB)。这个类有两个静态方法:ActivateProcessMainWindow,将激活一个给定进程的主窗口的进程ID(使用非托管API); GetSameNameProcess,将返回一个杀手级应用已经存在的实例的进程ID(使用仪器)。这个类的帮助下,我们可以正确地检查存在的其他应用程序的实例,以下列方式:
Dim pid As Long = AlreadyRunningChecker.GetSameNameProcess(False)

If pid <> 0 OrElse Command.ToLower().Contains("failmultiuser") Then

    MessageBox.Show("This application is already being run by another user.", _

        "Killer Application", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)

    Dim evlog As New EventLog_

        ("Application", Environment.MachineName, "Killer Application")

    evlog.WriteEntry( _

        "Multiple user execution was attempted. _

        User was notified and application terminated.", _

         EventLogEntryType.Information)

    Return

End If



pid = AlreadyRunningChecker.GetSameNameProcess(True)

If pid <> 0 Then

    AlreadyRunningChecker.ActivateProcessMainWindow(pid)

    Return

End If

我在互联网上从某处AlreadyRunningChecker类的大部分代码,但我不记得在哪里。对不起。5。设定数据目录的路径
我们已经谈过这之前的应用程序数据文件(所有应用程序文件,是不是代码)放置在不同的位置取决于应用程序是否运行在Visual Studio或使用生成的MSI文件安装。我们将使用全局变量Program.DataDirectory,来存储数据文​​件的实际路径。下面的代码将设置这个变量的内容:
DataDirectory = ConfigurationManager.AppSettings("DataDirectory")

If String.IsNullOrEmpty(DataDirectory) Then

    DataDirectory = Path.Combine(Application.StartupPath, "Data")

    If Not Directory.Exists(DataDirectory) Then

        DataDirectory = Path.Combine(Environment.GetFolderPath( _

        Environment.SpecialFolder.CommonApplicationData), "Killer Application\Data\")

    End If

Else

    DataDirectory = Path.Combine(Application.StartupPath, DataDirectory)

End If

If Not DataDirectory.EndsWith("\") Then DataDirectory += "\"

这段代码的功能是:检查如果该键使用DataDirectory存在appSettings节在配置文件中,其值不为空。如果是这样,使用DataDirectory设置其值。 (相对路径是指应用程序的可执行文件路径)否则,检查是否存在一个数据目录,应用程序可执行文件相同的目录中。如果是这样,这个目录的路径设置使用DataDirectory。否则,将使用DataDirectory常见的应用程序数据文件夹加上杀手级应用\数据。
2时,将适用于在应用程序运行或从Visual Studio内建成,将适用于安装应用程序时,和1个是为您要使用不同的数据与已安装的应用程序的特殊用途保留(例如,用于生产机器上调试)。有一个额外的事情后,已设置使用DataDirectory领域。其中一个杀手级应用的数据文件是数据库文件,通过类型化的DataSet访问。如果您在设置文件,你会看到连接字符串中使用如下:
Data Source=.\SQLEXPRESS;AttachDbFilename=

    "|DataDirectory|Database\KillerApplicationDatabase.mdf";

Integrated Security=True;User Instance=True

此连接字符串假定SQL Server 2005 Express是安装在本地。但看看AttachDbFilename关键:它指向的应用程序数据文件被放置目录。这个值被改变吗?是的,这就是我们做的事情:
AppDomain.CurrentDomain.SetData("DataDirectory", DataDirectory)

使用DataDirectory值,SQL Server引擎使用的是一个应用程序域范围的设置,可以设置AppDomain类的SetData方法。默认情况下,此设置不设置(即它的值是空),所以SQL Server引擎假定作为其价值的应用程序的可执行目录。由于我们可以在不同的地方的数据库文件,我们需要适当设置此设置,使SQL Server可以找到数据库文件。
此外,如果你恨全局变量,你可以直接使用此应用程序域设置的Program.DataDirectory变量,而不是获得的数据文件的路径。只需使用此代码来获得它的值:AppDomain.CurrentDomain.GetData("DataDirectoryquot;)。
然而,有这种方法的一个问题。有了这个连接字符串,只要你尝试编辑类型化数据集(例如添加一个新的TableAdapter),Visual Studio会抱怨它不能找到数据库文件。这是因为Visual Studio始终假定使用DataDirectory设置的默认值,因此,同时编辑数据集,你需要做的连接字符串中以下修改:
AttachDbFilename="|DataDirectory|Data\Database\KillerApplicationDatabase.mdf";

我敢肯定,必须有一个更好的解决办法,但我习惯了这一个,让我保持这样的模式。6。记录应用程序的执行
这是实际上没有必要,但我作为一个修改数据目录中的文件的例子(这在理论上是一个问题,卸载应用程序时,我们将在后面看到的原因,以及如何可以解决)。简单地说,包含当前时间和用户名的文本行是附加在数据目录(文件的解决方案,也没有安装包的一部分根名为log.txt的文件,这是第一次写入):
Dim log As String = String.Format("Application run by {0} on {1}{2}", _

    Environment.UserName, DateTime.Now, Environment.NewLine)

File.AppendAllText(Path.Combine(DataDirectory, "log.txt"), log)
运行应用程序
这里没有什么不寻常,我们只是通过控制应用程序主窗口:
Application.EnableVisualStyles()

Application.SetCompatibleTextRenderingDefault(False)

Application.Run(New FormMain())
打开和保存文件
测试用例2说:quot;验证最少权限用户不能修改其他用户的文档或filesquot;,和测试用例3说:quot;验证最小特权用户不能将文件保存到Windows系统directoryquot;好消息是,你并不需要做什么特别的东西,以满足这些测试用例,作为操作系统将适当的文件和文件夹授予或拒绝访问。您必须仅仅是一定要适当控制,试图读或写你(用户),其实没有被授权时,会抛出异常。
文件"菜单上的杀手级应用将帮助您与这些测试用例。它包含两个条目,打开和保存,允许创建并打开一个文本文件。任何生成的异常将被捕获并显示其相关信息。
保存对话框窗口看起来像这样:{五}
有一个文本框,您必须输入将创建一个文本文件的路径。
Try

    File.WriteAllText(Path.Combine(txtPath.Text, "KILLERAPP.TXT"), _

        "Congratulations! You have successfully created a text file _

            with Killer Application.")

    MessageBox.Show(Me.MdiParent, "Text file created successfully.", _

        "Killer Application", MessageBoxButtons.OK, MessageBoxIcon.Information)



Catch ex As UnauthorizedAccessException

    MessageBox.Show(Me.MdiParent, "Sorry, you don't have the necessary _

            permissions for creating a file here.", _

        "Killer Application", MessageBoxButtons.OK, MessageBoxIcon.Warning)



Catch ex As Exception

    Dim text As String = String.Format("Ooops. Unexpected error:{0}{0}({1}){0}{2}", _

        Environment.NewLine, ex.GetType().Name, ex.Message)

    MessageBox.Show(Me.MdiParent, text, "Killer Application", _

        MessageBoxButtons.OK, MessageBoxIcon.Error)

End Try
Dim photoPath As String = Path.Combine(Program.DataDirectory, "Photos\KaitoCute.jpg")

pictureBox.Load(photoPath)
Dim textPath As String = Path.Combine(Program.DataDirectory, "Texts\Agreement.txt")

textBox.Text = File.ReadAllText(textPath)
private const string APPNAME="Killer Application";

private const string APPFILE="KILLER APPLICATION.EXE";



private string ApplicationDataPath

{

    get { return Path.Combine(Environment.GetFolderPath

            (Environment.SpecialFolder.CommonApplicationData), APPNAME); }

}
1。安装
public override void Install(System.Collections.IDictionary stateSaver)

{

    if(!EventLog.SourceExists(APPNAME))

    {

        EventLog.CreateEventSource(APPNAME, "Application");

    }



    string userGroupName=FindUserForSid.GetNormalUsersGroupName();

    AclManager manager=new AclManager(ApplicationDataPath, userGroupName, "F");

    manager.SetAcl();



    base.Install(stateSaver);

}
2。
public override void Rollback(System.Collections.IDictionary savedState)

{

    if(EventLog.SourceExists(APPNAME))

    {

        EventLog.DeleteEventSource(APPNAME);

    }

    base.Rollback(savedState);

}
3。
protected override void OnAfterUninstall(System.Collections.IDictionary savedState)

{

    //* Delete data files



    string path=ApplicationDataPath;

    if(Directory.Exists(path))

    {

        try

        {

            Directory.Delete(path, true);

        }

        catch(Exception ex)

        {

            MessageBox.Show(string.Format(

@"Error when trying to delete the program data folder:

({0}) {1}



Uninstall process will continue, but the folder will not be deleted.

The folder path is:

{2}", ex.GetType().Name, ex.Message, path), APPNAME + " uninstaller",

MessageBoxButtons.OK, MessageBoxIcon.Warning);

        }

    }



    //* Delete the event source



    if(EventLog.SourceExists(APPNAME))

    {

        EventLog.DeleteEventSource(APPNAME);

    }



    //* Delete file from Prefetch folder



    string prefetchPath=Path.Combine

        (Environment.ExpandEnvironmentVariables("%windir%"), "Prefetch");



    try

    {

        string[] files=Directory.GetFiles(prefetchPath, APPFILE+"*.*");

        foreach(string file in files)

        {

            File.Delete(file);

        }

    }

    catch

    {

        string prefetchDir=Path.Combine

            (Environment.ExpandEnvironmentVariables("%windir%"), "Prefetch");

        MessageBox.Show(@"Some "+APPNAME+" files may remain in the

            "+prefetchPath+" directory. " +

            "You can delete these files manually.",

            APPNAME + " uninstaller", MessageBoxButtons.OK, MessageBoxIcon.Warning);

    }



    base.OnAfterUninstall(savedState);

}

{S3} {七}
%HOMEDRIVE%\vistatools\MsiTran.exe -a "$(ProjectDir)VistaPatch2.mst" "$(BuiltOuputPath)"

%HOMEDRIVE%\vistatools\MsiTran.exe -a "$(ProjectDir)AddMsiRMFilesInUse.mst"

    "$(BuiltOuputPath)"
cscript.exe "$(ProjectDir)NoImpersonate.js" "$(BuiltOuputPath)"
<?xml version="1.0" encoding="utf-8" ?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">

    <security>

      <requestedPrivileges>

        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

      </requestedPrivileges>

    </security>

  </trustInfo>

</assembly>
%HOMEDRIVE%\vistatools\Mt.exe -manifest "$(ProjectDir)setup.exe.manifest"

    -outputresource:"$(ProjectDir)$(Configuration)\setup.exe;1"

%HOMEDRIVE%\vistatools\signtool sign /f  %HOMEDRIVE%\vistatools\capsulekey.pfx

    /p kaitokun /v /t http://timestamp.verisign.com/scripts/timstamp.dll

    "$(ProjectDir)$(Configuration)\setup.exe"
最后请注意历史








感谢和问候

Error	1	The command "%HOMEDRIVE%\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\Mt.exe -manifest "C:\Users\Anubhav\Desktop\killerapplication_src\Killer Application\Killer Application\Killer Application.exe.manifest" -outputresource:"C:\Users\Anubhav\Desktop\killerapplication_src\Killer Application\Killer Application\obj\Debug\Killer Application.exe;1"

%HOMEDRIVE%\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\signtool.exe sign /f  %HOMEDRIVE%\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\capsulekey.pfx /p kaitokun /v /t http://timestamp.verisign.com/scripts/timstamp.dll "C:\Users\Anubhav\Desktop\killerapplication_src\Killer Application\Killer Application\obj\Debug\Killer Application.exe"

" exited with code 9009.	Killer Application
























PS。
至于,
查克诺里斯所有时间最伟大的扑克脸。他赢得了1983年世界扑克系列,尽管只持有一个小丑,一个Monopoloy监狱免费卡,俱乐部2,黑桃7和一个绿色的#4卡从游戏UNO.In电影"黑客帝国"查克诺里斯是矩阵。如果你付出密切关注绿色的"下降代码"的场面,你可以做出来,他beard.Chuck诺里斯淡淡纹理实际拥有IBM。







Dr.Luiji

信托,你会被信任。

回答