FileNotFoundException with CustomActions in Windows Installer
I'm building an installer with .NET 2.0 at the moment. I've been adding CustomActionData to the CustomAction dll, which includes a path. After adding a couple of new parameters, I started getting this message:
Now, I'm not actually trying to put the custom action in system32, it should be going under Program Files. The problem turned out to be a CustomActionData parameter. Here are the two values I tried - the first works and the second fails:
What seems to be happening is that the \" is escaping the quote. The installer must be putting extra parameters after the supplied string, which are used to locate the CustomActions dll. Because the last quote is escaped, the value of the hidden parameters is appended to my installpath parameter, and the installer "loses" the CustomActions dll. I think that this probably counts as a bug in the installer.
This one has been bugging me all afternoon, and I didn't have much luck with Google. I've laden this post with keywords, so hopefully someone else will benefit from my hideous afternoon. [n.b. we have no internal mechanism for recording findings like this, so I use this blog as a personal store for non-IPR work stuff].
Update: I needed too use [SourceDir] to, but this didn't work, unless there trailing slash was present!. This is the opposite of the previous behaviour, so the second one of these works and the first one fails. Weird.
Exception occurred while initializing the installation:
System.IO.FileNotFoundException: Could not load file or assembly
'file:///C:\Windows\system32\Files\Company\Product\CustomActions.dll' or one of its dependencies. The system cannot find the file specified..
Now, I'm not actually trying to put the custom action in system32, it should be going under Program Files. The problem turned out to be a CustomActionData parameter. Here are the two values I tried - the first works and the second fails:
/installpath="[ProgramFilesFolder][Manufacturer]\[ProductName]"/installpath="[ProgramFilesFolder][Manufacturer]\[ProductName]\"What seems to be happening is that the \" is escaping the quote. The installer must be putting extra parameters after the supplied string, which are used to locate the CustomActions dll. Because the last quote is escaped, the value of the hidden parameters is appended to my installpath parameter, and the installer "loses" the CustomActions dll. I think that this probably counts as a bug in the installer.
This one has been bugging me all afternoon, and I didn't have much luck with Google. I've laden this post with keywords, so hopefully someone else will benefit from my hideous afternoon. [n.b. we have no internal mechanism for recording findings like this, so I use this blog as a personal store for non-IPR work stuff].
Update: I needed too use [SourceDir] to, but this didn't work, unless there trailing slash was present!. This is the opposite of the previous behaviour, so the second one of these works and the first one fails. Weird.
/installedfrom="[SourceDir]"/installedfrom="[SourceDir]\"
15 Comments:
Are you supposed to post stuff that you write during work hours? Surely anything you produce during working time is owned by the company and is not yours to post for others to use.
Thanks for your comment - are you a colleague of mine? It's an interesting point you make, and one that I have considered in the past.
Firstly, when I started working for EurotaxGlass's, I told the CTO about my blog, and asked him what was appropriate to post. He replied that the only out-of-bounds area was source code that would give our competitors insight into our workings, and jeopardise our competitive advantage. So firstly, I have permission.
Secondly, this particular post doesn't relate to anything I have produced for the company, it is a work-around for bug in the installer technology in Visual Studio.
Thirdly, the principle I adhere to when blogging about things I do at work is to ask myself whether the company will lose out financially or otherwise from a particular post. I believe in this case, the company won't be harmed.
As a developer, when I come across a problem like this, one of the first things I do is to check out Google to see if anyone else has solved the problem before. More often than not, it's the bloggers who have the most useful information. This approach has saved me so much time I don't know how I coped before having internet access at work.
Because of this, and also because I'm a community sort of guy, I like to do the same thing. I get a buzz out of helping people solve problems. If you check out the comments on this post, that sums up why I put this kind of stuff on my blog.
We don't have a mechanism inside the company for logging this kind of issue, and if there was I would post it there too (although I think I'd still try Google first anyway).
You may be interested to know that one of my colleagues had an issue that he Googled for, and my blog came up in the results, and my blog post solved his problem. I actually helped the company by blogging - isn't that cool?
Anyway, thanks for taking time to comment.
Wow, thats a really naive comment.
How can something that somebody has learned (whether it be at work or not) be property of a company.
I think you are confusing the posting of generic (and helpful) information with the posting of company property (such as segments of actual source code).
By your logic when I change jobs, I would have to unlearn anything I learned in my current position.
by the way, the comment above is aimed at the original commenter, not Simon!
As the original poster, let me clarify what I mean:
No you dont have to unlearn anything (that is daft!), but work you do for a company in their time is their property. Work you do coding in your own time is yours to do with what you like.
Anyway, its your concience at the end of the day isnt it.
Man, you are really stubborn, do a favor to the world and let the developer's community grow. Simon you saved me so much time with your post!! You are the best
By the way....
I just asked my boss and she said it was OK to post -according to the Anonymous poster- my company's intellectual property:
I'm working on an installer for a web application which includes a CustomAction and it was working fine with the next parameters:
/OracleInstance=[EDTA1ORACLEINSTANCE]@/TargetDir="[TARGETDIR]\"
until I added one more:
/OracleInstance=[EDTA1ORACLEINSTANCE]@/TargetDir="[TARGETDIR]\"@/TargetVDir="[TARGETVDIR]\"
When I tried to run it I got this FileNotFoundException and after I read your blog I figured it out:
"[TARGETVDIR]" does not need an ending "\" whereas "[TARGETDIR]\" does.
/OracleInstance=[EDTA1ORACLEINSTANCE]@/TargetDir="[TARGETDIR]\"@/TargetVDir="[TARGETVDIR]"
Hope this helps some one else
Thanks for adding this ureyes84, and your kind comments. I'm glad you found it useful.
Thanks for posting this. I spent about 2 hours messing with this until I found your post. I owe you one, maybe I'll be able to share a tip with you some day.
Simon, these sort of pages are what makes the Web so fantastic. I've also been mucking around for hours on exactly the same problem, and this seems to be the only site that makes the problem & its solution clear. Thanks again!
Thanks for this, and like your previuos commenter, this is a great help. Unfortunately for me, I encountered the problem, found the the solution after hours of abortive searching!
What I did not do is post the answer on my blog - more fool me.
Well done- keep up the good work.
This may be obvious, but it hasn't been explicit stated.
The reason that some variables require the added trailing slash and some don't is that if the variable itself contains a trailing slash, a second slash will cause the first one to act as an escape character, so that you don't escape the end quote.
Example
if [TargetDir] is C:\My Program then no trailing slash is necessary since the quoted string "[TargetDir]" ends up looking like "C:\My Program"
If [TargetDir] is C:\My Program\ on the other hand, then "[TargetDir]" would yeild "C:\My Program\" and thus the end quote would get escaped, and your paramater would swallow ub the next parameter in line up to the next unescaped quote (i.e. bad things happen). To prevent this you can either add the trailing slash which yields "C:\My Program\\" thereby escaping the \ rather than the " or, if the program consuming the parameter is forgiving and Trims paths you could use a trailing space like so: "[TargetDir] ". The advantage of the trailing space is that it avoids the "does my variable end in a trailing slash or not?" question altogether and should work either way.
OMG! You totally saved me hours today. THANKYOU SO MUCH! I wanted to add $0.20 more to what I found when working with a CustomAction for a VSTO installer today. Here is how it went:
1) I copied the entire C# source code from an MSDN article which involved adding a 'ClickOnceCustomActions' custom action 'Installer' class to my setup project. It was virtually untouched by me. When I attempted to start testing this installer project for which it was added, I kept getting this error message:
"System.IO.FileNotFoundException: Could not load file or assembly 'file:///C:\Windows\SysWOW64\WMS' or one of its dependencies. The system cannot find the file specified.."
2) I attempted to add debugger break points and a call to: "System.Diagnostics.Debugger.Break();" as the first line in the overridden 'Install' method, but that code was never even reached. Because it was not reached, I thought I had a broken studio SP1 vs. SDK 6.1 issue--based on googling around. E-R-R-R!
3) I proceeded to worthlessly reinstall Visual Studio 2008, and the latest platform SDK, and reinstall the SP1 in precise orders... all of this was of course aimless and hazardous to the health of my virtual machine.
4) I was about to give up and create a brand new virtual machine environment from the ground up, when it dawned on me that:
a) Maybe the problem was in the code, but not in the c# part, maybe it was in the UI information, after I found THIS blog!
5) Sure enough! For my Custom Actions setup parameter under the 'Install' action, I was using the following CustomActionData string, because this is what was suggested by some MSDN documentation (e-r-r-r!):
/deploymentLocation="publish\"
As soon as I changed this CustomActionData string to this,
/deploymentLocation="publish"
...and re-tested, the error vanished! The installer execution stopped with a prompt, asking me if I wanted to debug the application with a new instance of a debugger, or with the existing open instance; I chose the existing instance, and the execution stopped on the "System.Diagnostics.Debugger.Break();" line of code I had added earlier in an attempt to debug the CustomAction C# code.
So in addition to the huge help this blog provided, I also learned that obviously, the information you enter into CustomActionData using Visual Studio 2008's IDE is somehow parsed and processed much earlier than the C# code behind this UI. That is very frustrating, yet once you understand it, you realize something very important!
Summary: If you have ANY obscure errors at runtime with your installer, the FIRST place you should look is not at the C# code behind the various studio designer UI classes. The very FIRST place you should check/eliminate are all of the expressions you added to various properties, succh as CustomActionData in this case. Check: spacing between '/X' type of arguments, all usages of quotes and other metacharacters like path delimiters (/ vs. \ for example) used in any expressions.
Why? Because if you cause a un-closed parens, or sans quote, or inadvertantly 'escape' a closing quote or bracket characters, etc., you will most likely corrupt the runtime ability to find installer-internal assemblies, or your own assemblies, etc.
I am so thankful that there are people like Simon out here in cyberspace willing to lend a free helping hand! Thankyou Simon, so much for posting this!
-Darrin.Wolf -at- gmail.com.
Darrin, thanks so much for commenting, and I'm so glad to have saved you some time. It's the main reason I posted it in the first place.
You've brought back memories of that afternoon for me (wow, nearly 3 years ago now). These kinds of things are so frustrating as they're not caught by the debugger.
Thanks for posting dude, this was really useful. I came into work early this morning and could have been stuck on this for hours, much appreciated.
Post a Comment