locked
The process cannot access the file because it is being used by another process.

    Question

  • Hi,

     

    I am trying to compile a workflow at run time,  i made a windows form includes a generated workflow at runtime, for the first compile everything is fine , if i am trying to compile it again without leaving the screen i got the following error :

    "Could not write to output file 'c:\\mydll.dll' -- 'The process cannot access the file because it is being used by another process. '"

    I used the following code :

     WorkflowCompiler compiler = new WorkflowCompiler();
        WorkflowCompilerParameters parameters = new WorkflowCompilerParameters(assemblyNames);
        parameters.LibraryPaths.Add(Path.GetDirectoryName(typeof(SendEmail).Assembly.Location));
        parameters.OutputAssembly = "mydll.dll";

        parameters.WarningLevel = 4;
        parameters.CompilerOptions = "/optimize";
        parameters.TreatWarningsAsErrors = false;
        parameters.GenerateInMemory = false;

        results = compiler.Compile(parameters, this.xomlFile);
        
        StringBuilder errors = new StringBuilder();
        foreach (CompilerError compilerError in results.Errors)
        {
         
         errors.Append(compilerError.ToString() + '\n');
        }

    Any idea please ?

     

    Thanks,

    Tarek Ghazali

    SQL Server MVP

     

     

     

    Monday, March 06, 2006 1:04 PM

Answers

  • You probably are holding onto a resource from the assembly.  Try using a different file name for the assembly.  However, if you are doing this quite a bit you will end up with lots of files so freeing up the resource might work better.
    Monday, March 06, 2006 5:03 PM

All replies

  • You probably are holding onto a resource from the assembly.  Try using a different file name for the assembly.  However, if you are doing this quite a bit you will end up with lots of files so freeing up the resource might work better.
    Monday, March 06, 2006 5:03 PM
  • Hi Tom,

    I can't use different file name for the assembly so it's not a good solution, and what is the meaning of "freeing up the resource " ?

    Thanks,

    Tarek Ghazali

    SQL Server MVP

    Wednesday, March 08, 2006 7:02 AM
  • Here is the method I am using to perform workflow execution, your needs may be a bit different, but this seems to be functioning properly.

    First, the code to actually run the workflow:

        try
        {
            // ensure that the latest version of the file is saved
            if (!this.Save(false))
            {
                MessageBox.Show("Unable to save file");
                return false;
            }

            //***NOTE: any assemblies loaded by this AppDomain will be unloaded with the Assembly
            //         [This lets us compile+run more than once]
            runtimeDomain = AppDomain.CreateDomain("WorkflowRuntime", 
                                    AppDomain.CurrentDomain.Evidence, 
                                    AppDomain.CurrentDomain.SetupInformation);
            runtimeDomain.Load(Assembly.GetExecutingAssembly().GetName());
            executor = runtimeDomain.CreateInstanceAndUnwrap(
    Assembly.GetExecutingAssembly().FullName, 
                                     typeof(WorkflowExecutor).FullName) as WorkflowExecutor;
                    executor.Initialize(this.XomlFile, this.RuleXomlFile, this.WorkflowClassName, this.WorkflowNamespace);
                    if (executor.Run())
                        MessageBox.Show("Workflow Completed Successfully");
                    else
                        MessageBox.Show("Workflow Failed to Execute");

                    return true;
                }
                finally {
                    executor = null;
                    AppDomain.Unload(runtimeDomain);
                    runtimeDomain = null;
                }

     

     

    Then, the WorkflowExecutor class [keep in mind this is still a work in progress]:

            internal class WorkflowExecutor : MarshalByRefObject
            {
                private string _xomlFile;
                private string _ruleXomlFile;
                private string _className;
                private string _namespace;

                private WorkflowCompilerResults compilerResults;
                private WorkflowRuntime workflowRuntime;
                private System.Threading.ManualResetEvent waitEvent;

                public WorkflowExecutor()
                {
                    waitEvent = new System.Threading.ManualResetEvent(false);
                }

                public void Initialize(string XomlFile, string RuleXomlFile, string WorkflowClassName, string WorkflowNamespace)
                {
                    _xomlFile = XomlFile;
                    _ruleXomlFile = RuleXomlFile;
                    _className = WorkflowClassName;
                    _namespace = WorkflowNamespace;
                }

                public bool Compile()
                {
                    if (!File.Exists(_xomlFile))
                    {
                        return false;
                    }

                    bool compileOK = true;

                    try
                    {
                        // Compile the workflow
                        //***NOTE: This is a custom configuration section that just stores the list
                        //         of potentially referenced assemblies, you can hardcode this list
                        //         as the sample did if desired.
                        WorkflowDesignerConfigurationSection config = ConfigurationManager.GetSection("WorkflowDesignerConfig") as WorkflowDesignerConfigurationSection;
                        if (config == null) throw new ConfigurationErrorsException("Missing Designer Configuration Section: WorkflowDesignerConfig");

                        String[] assemblyNames = new string[config.ReferencedAssemblies.Count];
                        for (int i = 0; i < assemblyNames.Length; i++)
                            assemblyNamesIdea = config.ReferencedAssembliesIdea.Path;

                        WorkflowCompiler compiler = new WorkflowCompiler();
                        WorkflowCompilerParameters parameters = new WorkflowCompilerParameters(assemblyNames);
                        //***NOTE: You may need to add some LibraryPaths here...
                        parameters.OutputAssembly = string.Format("{0}.{1}.dll", _namespace, _className);
                        if (_ruleXomlFile.Length > 0)
                            parameters.CompilerOptions = "/resource:" + _ruleXomlFile;

                        compilerResults = compiler.Compile(parameters, _xomlFile);

                        StringBuilder errors = new StringBuilder();
                        foreach (CompilerError compilerError in compilerResults.Errors)
                        {
                            errors.Append(compilerError.ToString() + '\n');
                        }

                        if (errors.Length != 0)
                        {
                            //***NOTE: Some sort of error notification should probably go here...
                            compileOK = false;
                        }
                    }
                    finally
                    {
                    }

                    return compileOK;
                }

                public bool Run()
                {
                    if (!this.Compile())
                    {
                        return false;
                    }

                    if (this.workflowRuntime == null)
                    {
                        this.workflowRuntime = new WorkflowRuntime();
                    }

                    workflowRuntime.StartRuntime();
                    workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowRuntime_WorkflowCompleted);
                    workflowRuntime.CreateWorkflow((compilerResults.CompiledAssembly.GetType(string.Format("{0}.{1}", _namespace, _className)))).Start();

                    try
                    {
                        waitEvent.WaitOne();
                    }
                    catch
                    {
                        return false;
                    }

                    return true;
                }

                void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
                {
                    this.workflowRuntime.StopRuntime();
                    this.workflowRuntime.Dispose();
                    this.workflowRuntime = null;

                    waitEvent.Set();
                }

            }


    Hope that helps...

    Friday, March 10, 2006 1:19 AM