views:

72

answers:

4

This is my Errormessage: Could not load file or assembly 'file:///C:\Windows\system32\Rule.dll'. The system cannot find the file specified.

The problem is that the same exe works in my development environment but not on productive server. The program is a tool that should run as a Scheduled Task on Windows Server 2008. It consists of an exe, one so called Database.dll and the Rule.dll. The exe should load the Rule.dll dynamically in codebehind but it fails with the above error only when started from Task Scheduler. Why is it looking in System32 folder and not in the Application folder? Is it an UAC-issue?

   'Load the rule engine into memory
    Dim asmRule As System.Reflection.Assembly = Nothing
    Try
       asmRule = System.Reflection.Assembly.LoadFrom("Rule.dll") 'fails on productive system
    Catch ex As System.Exception
       HistoryLog.writeLog("SysLog", ex, "Cannot find Rule.dll in Application Folder")
    End Try
+1  A: 

Set the task to 'Start In' the same folder as the exe (on Windows 7 this is on a property page on which you configure the path of the app to be run) - that way the current folder (from the environment) while the application is running is the same as the application folder. .Net should then use that folder when resolving non-rooted paths.

What you're seeing, I believe, is a common problem that you can also get with shortcuts.

That is - the startup folder is being set to the same as the root of the task scheduler - whose startup dll is in c:\windows\system32

The fact that 'it works on my machine(tm)' presumably is because when you debug it locally, you're running it directly?

The other answers here that suggest using BaseDirectory will also work.

Equally you could also change the code to using the full assembly name, and simply use Assembly.Load. However, this will break if the version/culture/publickeytoken of that DLL change in the future. Of course that could be mitigated by using a .config file to supply the name of the DLL to be loaded instead of hard-coding it. Which - in any case - is good practise.

Andras Zoltan
thanks for the detailed explanation
Tim Schmelter
+3  A: 

The method LoadFrom will use Environment.CurrentDirectory to build the full path to the assembly that will be loaded. The current directory is not the same as the application base path.

You should provide the full path to LoadFrom method, you can build it using AppDomain.CurrentDomain.BaseDirectory if the file is located in the same folder then the executable.

João Angelo
yes, that was the solution, thanks
Tim Schmelter
+2  A: 

Have you tried:

asmRule = Assembly.LoadFrom(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Rule.dll"));
RandomNoob
I will give it a try, thanks
Tim Schmelter
for the sake of completeness: asmRule = System.Reflection.Assembly.LoadFrom(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Rule.dll"))
Tim Schmelter
+1  A: 

Check the production server's system32 folder for a file called Rule.dll. The "probing" or attempt to load the assembly from a system folder could occur before the attempt to load from the Application folder.

This is a listed disadvantage of LoadFrom in MSDN:

If an assembly is loaded with LoadFrom, and the probing path includes an assembly with the same identity but a different location, an InvalidCastException, MissingMethodException, or other unexpected behavior can occur.

If this is the case and you cannot remove Rule.dll from system32, then you can specify a full path to the assembly.

P.Brian.Mackey
thanks for the explanations about the disadvantages, i will keep in mind
Tim Schmelter