如何编写代码只运行一次

时间:2010-12-21 21:29:23

标签: c# winforms

我正在寻找一种编写代码的方法,以便在程序首次启动时,这段代码只运行一次。如果程序已关闭并再次启动,则代码将不会再次运行。只有在卸载整个应用程序并从头开始安装树脂时,它才会再次运行。

数据库中的配置文件或标志不是解决此问题的方法。

我在某个地方(我似乎无法找到)读到一些基本上运行一次的方法,然后它可以基本上将一个变量编译成二进制文件,永远使用它。

感谢您对我的帮助!

8 个答案:

答案 0 :(得分:7)

你将不得不在某个地方存储州。你可以做很多很多地方,每种情况下使用的技术都不同:

  1. 在配置文件中(您明确拒绝)

  2. 在注册表中,有些人可能认为时尚,但肯定是一种选择。

  3. 在非机器网站,您编写的服务器或网站或类似网站上,但这需要基础架构和网络ping。

  4. 您可以执行类似于您建议的操作,动态重新编译DLL或程序,并调整源代码。这与配置文件没什么不同 - 除了配置文件是可执行文件之外 - 它还有一个缺点,就是很多时候受限制的用户都不能这样做,并且可能没有写入permssion,你想要存储它(例如在程序文件中。)

  5. 我相信还有其他方法。但是,像大多数编程问题一样,你必须考虑权衡,并确定哪个适合你。

    如果您可以提供更多信息和上下文(例如,为什么不能将其写入配置文件),也许我们可以帮助您更好地判断。

    如果它适合您,一个简单的解决方案可能是让安装程序添加一个名为的虚拟文件,例如,neverrun.txt。当您运行检查文件是否存在时。如果存在,请执行您的代码,然后删除该文件。这样就需要重新安装才能执行该代码。

    但是,这种方法存在许多问题。它不可靠安全(很容易建立起始状态并重新创建文件),您的用户可能无法删除Program Files中的文件或转储它的位置。我们需要更多的背景来理解你的基本目标。

答案 1 :(得分:4)

好的,无法抗拒,这是一个写入ADS流的版本。

using System;

namespace ConsoleApplication1
{
    class Program
    {
        private static string ADS_Part = "RunOnceFlag";
        private static uint FILE_FLAG_BACKUP_SEMANTICS = 0x2000000;
        private static uint CREATE_ALWAYS = 2;
        private static uint OPEN_EXISTING = 3;
        private static uint FILE_SHARE_READ = 0x1;
        private static uint GENERIC_READ = 0x80000000;

        static void Main(string[] args)
        {
            if (IsFirstEverRun())
            {
                System.Diagnostics.Trace.WriteLine("First run");
                SetRunOnce();
            }
            else
            {
                System.Diagnostics.Trace.WriteLine("I've been run at least once!");
            }
        }
        private static bool IsFirstEverRun()
        {
            //Current running EXE (assumes not being loaded from another program)
            string P = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
            string ADSFile = P + ":" + ADS_Part;

            //Try opening the ADS
            using (var FH = CreateFile(ADSFile, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero))
            {
                //Return whether its a valid handle or not
                return FH.IsInvalid;
            }

        }
        private static void SetRunOnce()
        {
            //Current running EXE (assumes not being loaded from another program)
            string P = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
            string ADSFile = P + ":" + ADS_Part;

            //Create the ADS. We could write additional information here such as date/time first run or run counts, too
            using (var FH = CreateFile(ADSFile, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, CREATE_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero)){}
        }


        [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        public static extern Microsoft.Win32.SafeHandles.SafeFileHandle CreateFile(string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            IntPtr lpSecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            IntPtr hTemplateFile);
    }
}

答案 2 :(得分:1)

您必须保留一个资源,例如文件或注册表值,以便向您的程序指示代码已经运行且不应重新运行。然后,您可以在启动时检查此文件/值,并且每当您要强制代码再次运行时,请删除文件/值。

示例:

  • 程序的应用程序设置目录中的临时文件。 (注意:您的卸载程序必须清理它)
  • HKLM / HKCU的注册表设置。 (注意:再一次,通过注册表清理)
  • 更改为app.configweb.config(注意:这不需要卸载清理,因为正常的卸载过程也应该删除配置文件,可能无法通过用户删除文件进行脏卸载)。

但这可能应该在您的安装/卸载步骤中完成。

答案 3 :(得分:1)

到目前为止在答案中没有看到,虽然这是一个老问题,但我还要在列表中添加一个选项:

  • 使用Windows服务作弊。每次启动应用程序时,它都会尝试安装该服务。如果已安装该服务,则不会再次安装该服务。现在,您可以选择在服务本身中添加额外的功能(在系统启动时运行它,要求它由您的应用程序运行,甚至更改程序以从服务启动而不是从原始快捷方式启动)。

根据您的需要,这可能是一个可行的解决方案。你在这里实际做的是在第一次运行和后续运行时改变程序的状态,你运行不同的代码:

if(!serviceInstalled)
{
    CodeThatRunsOnceAndOnlyOnce();
    InstallService();
}

但是,除非您通过该服务添加功能,否则更简单的解决方案以及我认为的事实上的解决方案是通过在注册表中保存状态。如果要将其从删除中隐藏,请对注册表项进行模糊处理。

答案 4 :(得分:0)

我注意到你的标签适用于Asp.Net和Winforms,在Asp.Net中有类似的东西有点奇怪,但为什么不把它添加到你的安装程序包中呢?

答案 5 :(得分:0)

在WinForms应用程序中,从应用程序启动代码调用代码,在ASP.NET应用程序中,从Global.asax中的Application_Start()处理程序调用它。 (我不知道你的应用程序如何兼顾。)

答案 6 :(得分:0)

配置项目设置,并将变量设置为标志...

您可以通过右键单击项目节点来执行此操作,然后转到属性和设置部分, 添加一个新的字符串变量

并通过以下方式访问它:.setting.defaults。 我想......

并设置它,设置变量后,需要调用save()

答案 7 :(得分:0)

您可以将它写在脚本中,因此在安装应用程序后,脚本会运行然后被删除。 或者在第一次安装后或者想要重新初始化应用时手动运行迷你应用。这样,您可以通过运行迷你应用程序来恢复全新安装。