Go Back   Winamp Forums > Developer Center > NSIS Discussion

Reply
Thread Tools Search this Thread Display Modes
Old 3rd May 2012, 21:41   #1
chief-pinhead
Junior Member
 
Join Date: May 2012
Posts: 6
Does "ExecWait" inherit admin ExecutionLevel on Win7? (DX redist installer failing)

Our product uses DirectX11, so as part of our NSIS installer, we want to install the DirectX runtime components on the target machine. Our NSIS installer uses "RequestExecutionLevel admin". We copy all of the DirectX redist files (.cab, .dll, .exe) into a temporary directory on the target machine, and then call
ExecWait '"${DIRECTX_TEMP_PATH}\DXSetup.exe"'

This approach has worked without problem for years, on Win7, Vista, and XP. But we recently upgraded to the June 2010 version of the DirectX redist files, and now the DX installer is failing with an internal error on some Win7 x64 boxes. The DX error log shows a few weird failures that could be explained by insufficient permission levels.
Also, on one of the "broken" systems we had the user launch the same DX redist installer manually by double-clicking DXSetup.exe directly, and it succeeded.
So there seems to be a difference between launching the DX installer directly vs. launching it from within an NSIS installer.

So that's my question - when I launch a process using ExecWait, does that process inherit the administrator privileges of the NSIS process?
If not, how can I give the DirectX installer process admin access?
If yes, then can anyone suggest an explanation for why this 3rd-party installer might fail when launched out of NSIS, but succeed when launched manually? Is there anything that I might do differently to avoid these failures?

Thanks in advance!
chief-pinhead is offline   Reply With Quote
Old 4th May 2012, 05:27   #2
MSG
Major Dude
 
Join Date: Oct 2006
Posts: 1,894
Yes, child processes inherit the access level of the parent. Keep in mind though that requestexecutionlevel is not guaranteed to get admin access. You must verify that you actually got it using the userinfo plugin. Proper way to do it: http://pastebin.com/EvMkyLLt

But assuming that the installer actually has admin access, I doubt it would be permissions related. What is shown in the logs?
MSG is offline   Reply With Quote
Old 4th May 2012, 20:38   #3
chief-pinhead
Junior Member
 
Join Date: May 2012
Posts: 6
Thanks for your reply MSG.
I added the code you suggested and confirmed that the NSIS installer does have admin privs on the "broken" machine.

I have two datapoints that exhibited this type of failure. On the first machine, after the NSIS-based DX install failed, we ran the same DX installer manually by double-clicking it directly. That succeeded. Unfortunately once it succeeds it will never fail again, as the DX redist cannot be uninstalled... So that test case is now gone.
Now I have one machine left that still fails. I am afraid to try installing DX manually, because if that succeeds, then that test case will be gone as well.

The DXError.log file on the second system contains just these two entries:

--------------------
[04/24/12 11:33:22] module: dsetup32(Apr 4 2007), file: dsinline.h, line: 302, function: DXRemoveFile

Unable to remove C:\Users\I7\AppData\Local\Temp\DXAA35.tmp.

--------------------
[04/24/12 11:33:22] module: dsetup32(Apr 4 2007), file: inline.h, line: 220, function: CleanUpDirectory

Unable to remove: C:\Users\I7\AppData\Local\Temp\DXAA35.tmp\infinst.exe which is locked, reason = 32.


"unable to remove" smells like a permissions issue. but note that hte installer failed severl more times without producing any other error messages, so these errors might be a red herring.

We've run the NSIS installer four or five times on the broken machine, and each time it invoked the DX installer, and each time the DX installer failed.
The first three times we got the "An internal error has occurred. please see the log files" dialog. Each time the DX installer did some work before failing, because more and more of the dll's that it is supposed to install were appearing on the user's system. But the DX logs were not updated properly at all. I can see a dozen or so dll's that were clearly added, but which do not show up in the system's DirectX.log.
When we repeated the test yesterday, the DX installer simply hung. No progress for 15 minutes before we killed it.

I'm at my wits end. Any suggestions or ideas that anyone has, please send 'em along, I'm open to trying them.

One other idea: Is it possible that the CWD could have been messed up when we call ExeWait? When I launch an exe by calling ExeWait form an NSIS script, what CWD does that exe receive?
chief-pinhead is offline   Reply With Quote
Old 4th May 2012, 21:28   #4
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 3,317
Is "C:\Users\I7\AppData\Local\Temp" the correct %temp% for that user?

Make sure you delete *.tmp in %temp% before testing again...

IntOp $PostCount $PostCount + 1
Anders is online now   Reply With Quote
Old 4th May 2012, 21:44   #5
demiller9
Senior Member
 
Join Date: Mar 2006
Location: Dallas
Posts: 453
The CWD is set with SetOutPath (typically before the FILE commands). ExecWait will not change it.
demiller9 is offline   Reply With Quote
Old 5th May 2012, 00:56   #6
chief-pinhead
Junior Member
 
Join Date: May 2012
Posts: 6
Anders: yes, the user's login is "I7", so "C:\Users\I7\AppData\Local\Temp" is the correct temp folder. In fact, that account is the system administrator account.
But I just found some additional error messages from a more recent failed installation attempt. It turns out the most recent DirectX redistributable stores its log files under C:\Windows\logs, which is a new location. We did not see those files at first. So the most recent DXError.log file contains two sets of error messages like these:

--------------------
[04/25/12 10:47:48] module: dxupdate(Mar 30 2011), file: dxupdate.cpp, line: 5738, function: DirectXUpdateInstallPlugIn

Failed API: SetupIterateCabinet()
Error: (1224) - The requested operation cannot be performed on a file with a user-mapped section open.

Unable to iterate through C:\Users\I7\AppData\Local\Temp\DIRECT~1\Nov2007_d3dx10_36_x64.cab. The file may be damaged.

--------------------
[04/25/12 10:47:48] module: dsetup32(Mar 30 2011), file: dxupdate.cpp, line: 280, function: CSetup::InstallPlugIn

DirectXUpdateInstallPlugIn() failed.

--------------------
[04/25/12 10:47:48] module: dsetup32(Mar 30 2011), file: setup.cpp, line: 1727, function: CSetup::SetupForDirectX

InstallPlugIn() failed.


I looked up that error 1224, and it seems to be saying that another process had a file handle open on the cab file that the installer was trying to extract. (I know for sure that the cab file itself was not corrupt - I did a binary comparison of the cab files in the temp folder with our installer source directory, and all files were copied cleanly.) I wonder who could be holding the open file handle(s).
My NSIS script executes these commands:

SetOutPath "${DIRECTX_INSTALL_PATH}"
File '${LocalResDir}\DirectX\*'
ExecWait '"${DIRECTX_INSTALL_PATH}\DXSetup.exe"' $3

Is there any chance that the "File" command is still hanging on to any file handles after the ExecWait begins execution? Could/should I do something to confirm that the files are actually ready for consumption?

I still think it must be somehow related to NSIS, because the other system that exhibited this failure had the same DX error messages, but on that system re-running the DX installer manually outside of NSIS succeeded. So in NSIS it failed, outside of NSIS it worked.

If anyone sees anything wrong with our approach, or has any suggestions for better practices, I am all ears.
Right now I have an installer that failed on 1/3 of all machines tested. And our only recourse is to detect the DX failure, tuck our tails, and ask the user to please double-click the DX installer manually. I don't like that option one bit.
chief-pinhead is offline   Reply With Quote
Old 5th May 2012, 05:24   #7
demiller9
Senior Member
 
Join Date: Mar 2006
Location: Dallas
Posts: 453
Could it be an antivirus program keeping it open while it is scanned? You might try a sleep before the ExecWait, or if you can detect the failure, immediately retry the ExecWait.
demiller9 is offline   Reply With Quote
Old 5th May 2012, 07:49   #8
redxii
Senior Member
 
Join Date: Nov 2005
Posts: 115
Which files does your program actually need from the DirectX runtime? You can simply use the File command to put the ones you need along where your program's main executable is. It'll install faster and reduce your install source size.

Only the .dll is needed with your program, not the .inf or .cat files.
redxii is offline   Reply With Quote
Old 5th May 2012, 08:00   #9
MSG
Major Dude
 
Join Date: Oct 2006
Posts: 1,894
But that probably wouldn't be legal.
MSG is offline   Reply With Quote
Old 5th May 2012, 12:07   #10
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 3,317
Quote:
Originally Posted by chief-pinhead View Post
Is there any chance that the "File" command is still hanging on to any file handles after the ExecWait begins execution?
Are you extracting this .cab? I assumed you only extracted the .exe. What is ${DIRECTX_INSTALL_PATH}?

Could you run Process Monitor to find out why some operation fails? (Maybe disk full or out of memory)

IntOp $PostCount $PostCount + 1
Anders is online now   Reply With Quote
Old 5th May 2012, 12:42   #11
MSG
Major Dude
 
Join Date: Oct 2006
Posts: 1,894
Quote:
Originally Posted by Anders View Post
Are you extracting this .cab? I assumed you only extracted the .exe.
The whole redist directory is extracted, I think:
Quote:
File '${LocalResDir}\DirectX\*'
MSG is offline   Reply With Quote
Old 7th May 2012, 14:36   #12
chief-pinhead
Junior Member
 
Join Date: May 2012
Posts: 6
Hi folks. Thanks for the ideas.

Anders: I am extracting every file that comes in the June 2010 DirectX redist package - one exe, two dlls, and 155 .cab files. Please look back at my NSIS script snippet for details. After all files are copied onto the target machine, I invoke the just-copied "DXSetup.exe" using ExecWait. That exe does a bunch of logic to decide what cab files need extracting, and then tries to extract them. Somewhere along the way it fails, apparently because some other process is holding an exclusive handle to the cab files, or to some other file-read-related shared resource.

As for the folder to which the DX files are extracted - I used to just "hard-code" the path:
code:
SetOutPath "$TEMP\DirectXSDK_install"


But once these problems started happening, I was worried that the files being extracted were perhaps corrupt somehow, so I started using a non-temporary path whose contents I could later inspect. So I now define

code:
!define DIRECTX_INSTALL_PATH "$INSTDIR\Install Media\DirectX Redist"



And I have verified that all 158 files are extracted correctly.

redxii - Microsoft is pretty clear in their documentation that you should run the redist installer hands-off, rather than trying to handle any of the logic or dll's manually. I don't believe manually adding the directX dlls is an option, even if it would allow our exe's to run.

It feels to me like AV is the most likely culprit.
I will run a test with a long sleep before the execWait.
And if we do get the failure, we'll use sysInternals to see who's holding the file handle. But I suspect that would come up empty - I bet the file handles are only held temporarily. Otherwise it would fail on the first cab file every time...

demiller9's idea is sort of pragmatic - just re-run if the ExecWait call returns failure. Unfortunately, the DX installer pops up a very nasty looking failure dialog of its own before returning, so I really can't wait that long. We need to prevent this problem, not react to it.

Thanks for everyone's ideas. Keep them coming!
chief-pinhead is offline   Reply With Quote
Old 9th May 2012, 19:19   #13
chief-pinhead
Junior Member
 
Join Date: May 2012
Posts: 6
I just encountered the error again, this time on my own system.
DXSetup.exe showed me the same "an internal system error has occurred" dialog, and then finished with a "Installation failed" dialog. Once I dismissed that, I was surprised to find that the return code reported by NSIS was "0" (success).

In other words, the NSIS command
ExecWait '"${DIRECTX_INSTALL_PATH}\DXSetup.exe"' $3
returned with $3 == 0, where I had expected it to return -9 (the return code for "internal error"). Also, the NSIS error flag is clear.

I was hoping I could at least detect a failure by inspecting the return value, so that I might pop up a "Please try installing DirectX manually" dialog.

Am I doing something wrong here? Is there another way to get the return value from invoking an exe?
chief-pinhead is offline   Reply With Quote
Old 9th May 2012, 19:50   #14
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 3,317
ExecWait should always report the correct process exit code, maybe a bug in the DX installer (Process Monitor also displays process exit codes (Might have to doubleclick the process-end event))

IntOp $PostCount $PostCount + 1
Anders is online now   Reply With Quote
Old 9th May 2012, 22:38   #15
chief-pinhead
Junior Member
 
Join Date: May 2012
Posts: 6
Thanks Anders. I used procmon and was able to "capture" a DX failure. Sure enough, DXSetup.exe returns exit status 0, right after showing me the "Installation failed" dialog. I guess I should not be surprised that Microsoft screwed that one up.

Sadly, I can't find a smoking gun in the procmon events, so we still don't know what is making the DX installer fail.

FYI: we have opened a paid service ticket with Microsoft to track this issue down. If I hear anything useful from them, I will cross-post the results here. Thanks for all the suggestions.
chief-pinhead is offline   Reply With Quote
Old 10th May 2012, 04:31   #16
redxii
Senior Member
 
Join Date: Nov 2005
Posts: 115
I just tried this and it worked.

code:
Section -DirectX

SetOutPath "$PLUGINSDIR\dxruntime"
File "directx\*"

ExecWait '"$PLUGINSDIR\dxruntime\DXSETUP.exe" /silent'

SectionEnd

redxii is offline   Reply With Quote
Reply
Go Back   Winamp Forums > Developer Center > NSIS Discussion

Tags
admin, directx, execwait, requestexecutionlevel

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump