Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Programatically copy a file to windows\system32 directory and Regsvr32 with Administrator rights

Status
Not open for further replies.

ManniB

Programmer
Nov 9, 2020
135
DE
Hi,

I'm using VFP 9.0 SP2 and InstallShield Express. During installation I need to copy a dll-file during to the c:\windows\system32 directory and register it with regsvr32, but couldn't find an option in Installhsield for accomplishing that. In Installshield there is an option to self-register, but it didn't help with this dll-file.

Then I tried to achieve this process after the installation upon running the application, by using foxpro commands.

I was able to register a dll file from within foxpro by using ShellExecute with Administration rights in this way:

DECLARE INTEGER ShellExecute IN shell32.dll ;
INTEGER hndWin, ;
STRING cAction, ;
STRING cFileName, ;
STRING cParams, ;
STRING cDir, ;
INTEGER nShowWin

ShellExecute(0,"runas","regsvr32.exe" ,"c:\windows\system32\myDLLfile.dll /s","",1)

I works well.

But I didn't find a way to copy a file to windows\system32 using ShellExecute.

Therefore, I tried a totally different apporoach:

I created a batch file with a script inside it, which first elevates the batch-file to have administrator rights and subsequently runs a copy command, then a regsvr32 command:

<!-- : --- Self-Elevating Batch Script ---------------------------
@whoami /groups | find "S-1-16-12288" > nul && goto :admin
set "ELEVATE_CMDLINE=cd /d "%~dp0" & call "%~f0" %*"
cscript //nologo "%~f0?.wsf" //job:Elevate & exit /b

-->
<job id="Elevate"><script language="VBScript">
Set objShell = CreateObject("Shell.Application")
Set objWshShell = WScript.CreateObject("WScript.Shell")
Set objWshProcessEnv = objWshShell.Environment("PROCESS")
strCommandLine = Trim(objWshProcessEnv("ELEVATE_CMDLINE"))
objShell.ShellExecute "cmd", "/c " & strCommandLine, "", "runas"
</script></job>
:admin -----------------------------------------------------------

xcopy C:\myapp\myDLLfile.dll c:\windows\system32 /D/S/Y/R/E/F/G/H
regsvr32 C:\windows\system32\myDLLfile.dll


When running the batch-file by dobble clicking it in windows explorer, everything works fine.

But when I run the batch file from within VFP by the command "RUN C:\myapp\mybatchfile.bat", the batch-file isn't able to copy the dll-file to windows\system32. Interestingly, the registration part (regsvr32) works flawlessly, when first manually copying the dll-file in the windows\system32 directory. But the copying is simply not performed, there is no error message either.

Is there any way to solve this somewhat "simple problem" of copying a file to windows\system32 and registering it (administration rights needed)? Moving away from Installshield Express to another program like Inno Setup would be too difficult and time consuming for me at the moment.

Any help would be highly appreciated.

Thanks,
Manni




 
Your first error is assuming the wrong system folder for the DLL. It needs to be in SysWow64, unless you have a very old Windows 32bit only version. Also, you need to use regsvr32.exe from SysWow64.

AFAIK the Installshield express had one more possible solution besides self-registering, but I haven't used it in a while. I also think the best location for any application related ActiveX controls or COM Server DLLs is the application folder. Unless you plan multiple applications using the same DLL.

Take a look at Inno Setup, that'll also give you more control.

Chriss
 
Is there any special reason that you need to install the DLL in the system folder? It would make more sense to install it in the same folder as your application (as Chris has suggested). InstallShield will be able to do this perfectly well, and there should be no problem with Regsvr32.EXE: you just need to pass the full path and file name.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Manni,

indeed, System32 is some kind of relic of 32bit windows. Nowadays, 32bit win versions are hard to find, mostly on old tablets or convertibles or really, really old desktops.

With Win64 M$ introduced a new directory that is essential for 32bit app devs: SYSWOW64
Well, indeed this name is absolutely irritating and should have been called SYSW32onW64, that way its purpose might have been more obvious :).

SYSWOW64 simply means "Windows 32bit System files on a windows 64bit system". Most DLLs are redundant in System32 and SYSWOW64 but devs have to place their DLLs in the NEW directory to make them accessible. For registering a 32bit DLL on Win64 you have to use the regsvr32 from SYSWOW64. Well, this might be a bit irritating, but...thats the way M$ handles it.

HOWEVER: As long as you only use this DLL in your own app and not available for other apps, you should place the DLL in your apps installation directory. Your EXE will find the DLL without any registration at all, no matter if the installation diretory is local or on a fileserver.

-Tom
 
Thank you for your insightful answers!

Yes, there is a special reason why I have to place the DLL file in the system32 directory. It's the Soundrecorder.exe which also needs the Wavdest.dll file, both have to be in the system32 folder to work and Wavdest.dll has to be registered. The Soundrecorder isn't supplied with Windows 10 anymore (Windows 8.1 was the last Windows which came with a Sound Recorder).

Using Installshield Express I tried to install the files (Soundrecorder.exe and Wavdest.dll) in the Windows\system32 folder. Surprisingly, the files are not installed in system32, but Installshield automatically puts them in the syswow64 directoy (that's why I first thought Installshield failed). The only problem now is, Installshield is not able to register Wavdest.dll automatically by choosing the self-registration option. After manually registering the file Wavdest.dll in the syswow64 folder, Soundrecorder works properly on Windows 10.

To register the file after the installation programatically, I use the following commands:

DECLARE INTEGER ShellExecute IN shell32.dll ;
INTEGER hndWin, ;
STRING cAction, ;
STRING cFileName, ;
STRING cParams, ;
STRING cDir, ;
INTEGER nShowWin

ShellExecute(0,"runas","regsvr32.exe" ,"c:\windows\system32\WavDest.dll /s","",1)


However, the user still has to say yes in the administrator window which is windows is opening after the last command is executed. I guess there is no way to avoid this?

Or is there another way to let Installshield Express register the file after installation?




 
It's likely Installshield itself, which is the problem because in itself it's a 32bit process and therefore automatic redirection of access to system32 by 32bit processes to syswow64 doesn't only put the DLL and EXE into syswow64 but also uses the regsvr32 from syswow64.

So what you need is a setup that's 64bit. Installshield Express was just given as basic installer for VFP applications, so again take a look at Inno Setup, it explicitly mentions to be able to create 64bit installers as a key feature.


Chriss
 
Hi Chris,

this is what I feared, that InstallShield fails to register the file and I would have to switch to Inno Setup, what I don't want to at the moment, just because of this one file. Interestingly enough, Installshield manages to register other dll files if you select "self register" flawlessly. Only with the WavDest.dll file, which comes from Windows 8.1, does it fail.

The options you can choose in Installshield when you right click on the file are "none", "self-registration" and "Extract COM information". I tried all of them and none of them work. Why does Installshield have such a problem to register this file, when it can do this with other dll files without any problems? When manually registering the dll-file oder using ShellExecute, there is also not a problem.

I don't understand why you would need a 64-bit installer to register the dll-file via regsvr32? Are there two different versions of regsvr32.exe? Could you please explain this to me what't the connection with Syswow64, it's confuses me.


EDIT:
During installation InstallShield gives the error megssage:

hresult -2147220473 Module C:\Windows\Syswow64\WavDest.dll
failed to register. HRESULT -2147220473. Contact
your support personnel.

I found a similar topic in another forum Link.

There the only solution seamed to be to deactivate UAC (User Account Control). But after deactivating UAC I still get the error message.



 
Hi Manni,

Microsoft has decided to separate several things regarding bitness. So there are tools, not just regsvr32.exe, which exist in 32bit and 64bit, yes two versions and they don't differ in their name. To stay downward compatible, Microsoft could have made things much simpler by introducing a System64 folder. Instead, they make 32bit processes access SysWow64 when they try to access System32. That's not just confusing to you, that already confused generation after generation of programmers and CPUs ;).

The separation of program files is not that much better. But the separation also continues with a 32bit and 64bit section of the registry and that's also where registration can fail.

Turning off UAC control indeed gives a process more freedom to access certain system folders which normally need elevated rights like you do have with a setup. But you do have this elevation already and as you can see from the Installshield installer, the redirection still occurs.

There's also a chance the DLL has another dependency, you may want to test this using dependency walker (depends.exe), just google it to find it.

Chriss
 
Thank you, Chris, I'm glad I'm not the only one getting confused ^^

So for example the regsvr32.exe: There is one in system32 and one in SysWOW64. Are they both 32-bit applications or is the one in SysWOW64 a 64-bit application? I thought, as Tom Borgmann said before, that you can think of it as SYSW32onW64. So it means it contains 32-bit applcations?

When Windows makes 32-bit processes access Syswow64 instead of system32, why is there still a system32 directory on a 64-bit operating system?

When Installshield Express registers DLL-files (after choosing the self-registration otion in ISE), is it using regsvr32 from system32 or from SysWOW64?

Respectively, which one is used when you use the comamnd: ShellExecute(0,"runas","regsvr32.exe" ,"c:\windows\system32\WavDest.dll /s","",1) ?

Thanks,
Manni

PS: I'm sorry for these beginner questions, just trying to understand this topic.
 
It's still confusing and you might need to read it up many times, but System32 is the 64bit folder and SysWow64 the 32 bit folder. There is a 32bit Version of regsvr32.exe in SysWow64 and a 64bit version in system32. That's what's confusing everybody.

A more detailed explanation of the diferences is here:

Regarding Installshield Express itself is a 32bit application, so it also doesn't have the concepts of 64bit system folders, it thinks the system32 folder is still the 32bit folder, just like you think it is, therefore the redirection. And since it's not ISE running during a setup but the setup.EXE it creates or an MSI package, that's the stage at which the wrong destination system32 is redirected to Syswow64. Just when you really indeed want to install something that's 64bit this redirection is counterproductive.



Chriss
 
Thank you Chris, this makes more sense now after reading your answer and the article.

1) So when you register a DLL-File stored let's say on the Desktop and registering it with a regsvr32 command, Windows will automatically choose the right regsvr32 (32-bit or 64-bit) depending on whether the dll file itself is 32-bit or 64-bit?

2) And when the DLL file is placed in system32, Windows will register it using a 64-bit regsvr32? Respectively, when placing the file in syswow64, windows will choose a 64-bit regsvr32? (no matter if it's a 32- or 64-bit dll ?) And this could lead to an error if you put a 64-bit DLL in the syswow64 directory and trying to register it, because windows will use a 32-bit regsvr32.exe ? --> If this ist true, then why can I manually register the 64-bit dll file in the syswow64 directory and don't get an error from windows? But when Installshield tries to register the file, there appears an error. ??





 
The system isn't as intelligent as you expect it to be. So let me go back to the ShellExecute question you already asked two posts ago and I didn't answer yet:

When a 32bit process like a VFP EXE calls ShellExecute you also get the 32bit regsvr32.exe to runas admin and try to register the 64bit DLL. When you try to explicitly specify the 64bit regsvr32.exe in System32 the folder redirection lets you call the 32bit version again, you don't get to where you want to get with this.

Why does it work when you manually do this? You run the Desktop (64bit) maybe a Windows Explorer (64bit) and cmd.exe (again 64bit) and thus even when you would try to run the Syswow64 regsvr32.exe you run the 64bit EXE and it can register the DLL.

The location of the DLL isn't that important, but most DLLs do have further dependencies from API calls in system DLLs or a C/C++ runtime and that must be the correct bitness, but indeed you can register a VFP COM-Server DLL the setup copies anywhere - given the vfp9r.dll and the msvcr71.dll are also present or can be found in SysWow64.

The simplest solution to get this one correct regsvr32.exe call would perhaps be using PowerShell. But that requires Windows to allow PowerShell scripts to execute. In general, this is disabled or set to only allow signed scripts.

You have the option to run a 64bit EXE from a 32it VFP EXE via RUN, but it can't be a 64bit EXE in System32, it would need to be somewhere else, so maybe you add the 64bit regsvr32.exe from System32 into the setup, let it be copied to your application installation folder and register the DLL with it, which you also simply put into the application folder.

Chriss
 
Thank you, Chris.

The reason, I want the let Installshield do the registration, is so there is no user interaction needed after the installation process. So far, I have been able to register the dll-file after installation with VFP using using ShellExecute, but the user has to confirm the registration, because admin rights are needed. I wanted to avoid this second user interaction after the installtion of the setup.exe created with Installshield.

So my new idea is, to find a 32-bit Version of Soundrecorder.exe and the corresponding Wavdest.dll and try to let Installshield register it choosing the option "self-registration". I don't know if it will work.

General question: So far I only used Installshield to register 32-bit ActiveX (dll-files) during installation. Does Installshield Express (the one coming with Visual FoxPro) have the ability to register 64-bit dll files at all?

 
Manni said:
Does Installshield Express (the one coming with Visual FoxPro) have the ability to register 64-bit dll files at all?
The Express version is very limited. I don't think you can specify any script or batch or command to run, so you're limited to 32bit. If you find something like that you can make use of the idea to run the 64bit version of regsvr32.exe installed into your application folder.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top