VB.Net Program Can't Edit HKEY_LOCAL_MACHINE In Registry - vb.net

At work we are constantly juggling multiple licenses of a software package. The license key is stored in the registry in HKEY_LOCAL_MACHINE so I wrote a Windows Batch File that when run as administrator, edits the registry key to one of the license strings.
Most recently I've written a GUI based application in VB.net that uses the software package's API to add some cool functionality. I also wanted to include a GUI based license switching module to make the juggling even easier. However, I haven't been able to succeed in doing so.
I've tried multiple methods, running the program as Administrator:
Using VB.Net's Registry module
Dim key As RegistryKey = Registry.LocalMachine
Dim autoshell As RegistryKey
autoshell = key.OpenSubKey(registryKeyDirectory, True)
autoshell.SetValue("Software", licenseKey)
autoshell.Close()
Running a .reg script
Dim p As New ProcessStartInfo
p.FileName = "regedit.exe"
p.UseShellExecute = True
p.Arguments = """C:\test.reg"""
Process.Start(p)
Sending the Registry edit command to CMD
Dim process As New Process()
process.StartInfo.FileName = "cmd.exe"
process.StartInfo.Verb = "runas"
process.StartInfo.UseShellExecute = True
process.StartInfo.Arguments = "/K reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Software\Licenses\Serial Numbers"" /f /v ""Software"" /t REG_SZ /d """ + licenseKey + """"
process.Start()
Running the Windows Batch Script through CMD in a similar way to above
'Code is much the same as above
All of these methods worked perfectly with editing a Key in HKEY_CURRENT_USER. I thought it might be the particular key and the permissions relating to it, but after further testing I found that none of the above code could edit any arbitrary key in HKEY_LOCAL_MACHINE.
I've looked at just about every link on Stack Overflow relating to this and no-one seems to be having the same problem as me. I suspected it might have to do with the privileges of my user account on the office network, so I took the code and tested it on my home PC but to no avail.
At this point I'm really at my wit's end and would greatly appreciate any help!
Thank you in advance for reading :)

This is caused by the Registry Redirector. (Noted: This link seems to be written in the win7 era and kind of outdated). Your program is 32-bit, when running on a 64-bit OS, the call to registry is redirected to the 32-bit logical view of the registry.
In Visual Studio, compile your program to target AnyCPU, also uncheck the "Prefer 32-bit" checkbox. Then the program would run as 64-bit on 64-bit OS, and 32-bit on 32-bit OS.

Related

AnyCPU COM library (.tlb file) not working when called from external VB6 macro in x64

Okay my title might not be clear enough. I work with an application for which we can develop VB6 macros. This macro needs to work with a .NET dll that I also developped. When I launch the application in x86 mode and I try to run the macro, it's working fine, I can access the methods of the class and everything.
But when I do the same in x64 mode I get the error : "Automation server can't create object"
What's really strange is that I'm not using any x86 unnmanaged COM dll which would be a problem with an x64 architecture. When I do : "Dim myClass as new MyClass.App" it's working but when I call for example a myClass.Start() method, I get this error. And I tried just having a MsgBox('hello world') in my Start method, to be sure it had nothing to do with my code, still no luck. I'm linking my macro to my class with a TLB file.
I tried registering my DLL with RegAsm, but it's still not working in x64. Is there a way to generate both x86 and x64 versions of my TLB? Then I would add both references and if the x64 version throws me an error on Start method, I simply call the x86 method (not a perfect solution, but still..).
Any idea how to solve this problem?
As Hans said, I needed to user the 64-bit version of Regasm.exe. Even though I had already tried launching RegAsm manually after my installation, it was not working. First I added that in the post-build event of my project :
"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe" "$(TargetPath)"
That did the trick for the Debug version. What's strange is that the AnyCPU version was working fine at first on my x64 application, in debug mode, it started crashing when I created my setup project (no idea why...). But this change doesn't solve my problem when installing the application, so I added this in the "Commit" of my custom action (based on this article : Regasm- 64bit or 32bit though windows installer in visual studio) :
Public Overrides Sub Commit(savedState As System.Collections.IDictionary)
MyBase.Commit(savedState)
'Check if we're on a x64 OS
If Environment.Is64BitOperatingSystem Then
'Get the Windows dir on the current computer
Dim winDir As String = New IO.DirectoryInfo(Environment.SystemDirectory).Parent.FullName
'Define the path to regasm for x64 machines
Dim regasmPath As String = IO.Path.Combine(winDir, "Microsoft.NET", "Framework64", System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion, "RegAsm.exe")
If File.Exists(regasmPath) Then 'Si le chemin existe, on enregistre la DLL
'Get the location of our DLL
Dim componentPath As String = GetType(Installer).Assembly.Location
'Executes regasm
System.Diagnostics.Process.Start(regasmPath, "/codebase """ & componentPath & """")
End If
End If
End Sub
What I changed from the original article is the path to RegAsm. Since my setup is x86, the RuntimeEnvironnment's directory was pointing to the "Microsoft.NET\Framework..." path not the "Framework64" which was defeating the purpose of my action (it was already registered as a 32 bit COM interop), so I try to get the x64 version of RegAsm and run it.

How to set wix msi to run advertised by admin

I have a program that auto-updates itself when it finds a newer version MSI. I used to create the MSI with a VS2008 Setup project. I migrated the development to VS2013, lost the Setup project, tried IS and got extremely frustrated and finally landed with WIX.
The MSI created with WIX does all I need but fails in the auto-update logic:
Because the program can be running under a limited user account, when it detects a newer MSI, it first Advertises it with the credentials of an Administrator. These credentials are stored encrypted in an XML file.
Then, once the MSI has been advertised, it is launched with the current user. The code (in short)
Process^ advertise = this->advertiseMSI(shortpath,mydomain,myusername,mypassword);
advertise->WaitForExit();
Process^ install = this->installMSI(shortpath);
Where advertiseMSI is:
Process^ process = gcnew Process();
process->StartInfo->UseShellExecute = false;
process->StartInfo->FileName = "C:\\Windows\\System32\\msiexec.exe";
process->StartInfo->Arguments = "/jm " + "\"" + msiPath + "\"";
process->StartInfo->WorkingDirectory = Environment::GetEnvironmentVariable("WINDIR");
process->StartInfo->UserName = userName;
process->StartInfo->Password = this->getSecureString(Password);
process->StartInfo->Domain = userDomain;
process->StartInfo->Verb = "runas";
process->Start();
return process;
and installMSI just launches the Msiexec in a silent install with the current user.
This worked fine with the MSI created with VS2008 but it fails with the WIX MSI.
The log of the msiexec is:
"Error 1730. You must be an Administrator to remove this application..."
If I run the MSI manually, it works when logged as admin but when logged as user it fails and doesn't ask for elevating privileges.
I have set InstallPrivileges="elevated" InstallScope="perMachine" in the Package section and does not make a difference (I have tried every possible combination of those). It seems to me that the MSI is not advertised but the code does not fail. Looks like the MSI is always run with limited privileges.
I have also tried to set AllowAdvertise="yes" in the only one Feature of the product.
One main difference I can see with the MSI produced with VS2008 is that the later had two features, Admin and user.
I don't know if you're still struggling with this problem, but I've come across a similar problem with an installer built with NSIS, so perhaps this will help you or others. I was able to overcome this in my situation by using command shell indirection as follows (C# code):
ProcessStartInfo processInfo = new ProcessStartInfo("cmd", "/C myapp_installer.exe /S /D"); // Options /S /D apply to myapp_installer.exe.
processInfo.UseShellExecute = false;
processInfo.Domain = domain;
processInfo.UserName = username;
processInfo.Password = password; // Obtain securely not hard-coded.
Process process = Process.Start(processInfo);
I can't fully explain why this works, when directly calling the installer fails to pass the required credentials, but I'm pretty certain that it has to do with what is explained by Chris Jackson on the MSDN Blog, which incidentally was referenced in the answer to your related question.
I hope this helps!

Trouble with msi exit code 1625 when running msi programmatically

Exit code 1625 is "This installation is forbidden by system policy. Contact your system administrator."
What I'm doing is calling it this way:
Process installProcess = Process.Start(msiPath, "/quiet");
I can run the msi fine if I open it manually. This is on windows server 2008...
The intent of this is to automatically update my .net forms program with the latest version. Anybody have a clue what sort of setting is causing this? I mean, the clients are going to be using vista/7/xp, but I still need to know what kind of security settings will ruin my plan.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Arguments = "/i " + "\""+Directory.GetCurrentDirectory()+"\\"+msiPath +"\"" +" /q";
startInfo.FileName = "msiexec.exe";
startInfo.Verb = "runas";
Process installProcess = Process.Start(startInfo);
Calling the msi this way did the trick.
Turned out to be some kind of UAC issue I think. The runas verb somehow elevates the permissions the program has. Even though my UAC prompts were disabled on server 2008 I still had to do this to get around it.. strange huh?

System.Process.Start - running msi problem

When i try to run a msi using System.Process.Start("test.msi") in a vb app i get the following error.
The installation package could not be opened. Contact application vendor...
Msi file works fine when double clicked, tried System.Process.Start with text files and exe files and they work fine, problem only with msi
files. Running vista. Also tried xp but no luck
Thanks
If you have a setup.exe with your msi, run that instead. Otherwise, use this code:
Process p = new Process();
p.StartInfo.FileName = "msiexec";
p.StartInfo.Arguments = "/i PathToYour.msi";
p.Start();
(from here: MSI doesn't run from within C#)
The reason for needing to do it this way is that when you do System.Process.Start("file.txt") it will work since it is (sort of) calling notepad.exe %1 which will work for a text file but msiexec %1 will not work for a msi, since msiexec has a required parameter (Option).
You can test this yourself, by trying msiexec file.msi on the command line - it will give you this helpful little message:
To help pinpoint the problem, try running some other .exe from your code, like notepad.exe.
System.Process.Start("notepad.exe")
Had the same problem. The problem lies on declaring the path of the msi. You need to put double quotes around it.
Instead of
p.StartInfo.Arguments = "/i PathToYour.msi"
try
p.StartInfo.Arguments = "/i ""PathToYour.msi"""

Running VBScript from UIAccess VB app using MSScriptControl

I'm trying to run some VBSCRIPT from within my application. This works fine when I run my program from within VB. But once I add "UIAccess=true" to my manifest and digitally sign my exe with my certificate, I am unable to run the code any more. It gives errors when I try to interface with any program saying "429: ActiveX component can't create object: 'myApp.Application'". Anyone have any idea why it would run fine in the IDE but not with an application with uses UIAccess? Here is the code:
Dim scriptRunner As New MSScriptControl.ScriptControlClass
scriptRunner.Language = "VBScript"
scriptRunner.AllowUI = True
scriptRunner.Timeout = 3000
scriptRunner.AddCode(scriptStr)
scriptRunner = Nothing
In googling around, I found this website.
it says
Applications with the uiAccess flag set to true must be Authenticode signed to start properly. In addition, the application must reside in a protected location in the file system. \Program Files\ and \windows\system32\ are currently the two allowable protected locations.
maybe it works in your IDE because your IDE is within \program Files\, but outside of your IDE you are running the signed application NOT within \program files or \windows\system32