I am running an automated test using C# and Coded UI Tests on Window Server 2016. I am using the process.start method to launch an installer but when the test launches the installer, the window is blank and cannot be used either by the test or manually.
This does not happen when I launch the installer manually (works fine) or on any other OS (only happens on Server 2016).
Everything is running as admin. I have updated windows itself and video drivers.
Here is the code used to launch the installer:
public void LaunchUnifiedDashboardInstaller(bool upgrade = false)
{
string pathtoInstaller = "";
// Get path to installer
if (upgrade == false)
{
pathtoInstaller = TestRunSettings.TestSetting.GetPathToInstallers();
}
else if (upgrade == true)
{
pathtoInstaller = TestRunSettings.TestSetting.GetPathToUpgradeInstaller();
}
//string pathtoInstaller = #"E:\";
Console.WriteLine("LaunchUnifiedDashboardInstaller() - Path to installer is: " + pathtoInstaller);
TestReport.WriteText("Launching Unified Dashboard setup .... ");
//Server Installer
System.Diagnostics.ProcessStartInfo proc = new System.Diagnostics.ProcessStartInfo(pathtoInstaller + #"\setup.exe");
//proc.UseShellExecute = true;
//proc.Verb = "runas";
System.Diagnostics.Process.Start(proc);
TestReport.WriteText("Launching Unified Dashboard setup .... ");
}
screenshot of blank windows
This one has me totally stumped. Has anyone seen this before?
Thanks
Richard
Fixed it. Sort of.
This was happening using Server 2016 with all the available updates applied.
So I went back to the base original release of Server 2016 (from 2016) and turned off Windows update. Lo and behold, it now works fine. Something in a newer Windows version must have disagreed with Coded UI.
Related
My console application is responsible for starting a WCF service in interactive mode (ie. the service does not get installed as a Windows service in that case).
In order for my application to start the latter, the application invokes the compiled executable using the following method:
static bool AutoStartService()
{
var MyProcessFile = System.IO.Path.GetFullPath($"pathToExecutable/MyServiceExe.exe");
Process myProcess = new Process();
myProcess.StartInfo.FileName = MyProcessFile;
myProcess.StartInfo.Arguments = "";
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
myProcess.Start();
Thread.Sleep(WaitForTheServiceToStart);
}
return true;
}
Note that this approach works just fine when debugging from Visual Studio.
However, when the console application is invoked from Jenkins (note that I gave Jenkins admin access and it logs in as a normal user), then the service process does not seem to stick or be visible from the Console application. I can tell it at least starts and stops as I can see the logs being written to file.
The Console application is started using a batch command from Jenkins (I also tried using Powershell, but without luck).
Any suggestion on how to do that?
I have tried with both debug and release builds of my Console app C# project, but it makes no difference.
EDIT
I have edited the following properties, but without success:
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.Environment.Add("BUILD_ID", "dontKillMe");
I am now seeing the following warning, but I don't believe installing the service is the only way to go as this is what I am doing when running this code without Jenkins and it works. Maybe Jenkins does not allow it though?:
Cannot start service from the command line or a debugger. A Windows Service must first be installed (using installutil.exe) and then started with the ServerExplorer, Windows Services Administrative tool or the NET START command.
EDIT2
I went a step further. The reason why I was getting the former message is that the service checks "Environment.UserInteractive" to either run as interactive or to start/run the installed service. For some reasons this flag is always set to false, while it should be true in my case.
Is there a way to fool the service to think that flag is true?
I have created a Windows shell extension that provides a menu to users when they right-click in File Explorer. This then invokes a small dialogue App.
I'm a novice at software development so there is probably some schoolboy error I'm making but I just can't see it.
For testing purposes I am hard-coding the path to the EXE and ensuring it's present on the VM.
private void CallExteralAddLocation(string sFullPath)
{
string sEXE = Path.Combine(Application.StartupPath, "AddLocation.exe");
WriteLog(sEXE);
// during testing, hard-code this path
sEXE = "C:\\temp\\AddLocation.exe";
System.Diagnostics.Process.Start(sEXE, sFullPath);
}
private void WriteLog(string sText)
{
using (StreamWriter sr = new StreamWriter("C:\\Temp\\ShellExtLog.txt"))
{
sr.WriteLine(sText);
}
}
It works fine on my host machine but when running on a VM running Windows 10, which is where I am testing it, the dialogue App does not get invoked.
I have checked that I can invoke the AddLocation.exe from a command window on the VM and that works as expected. So it looks like it's just not getting called.
As it's a shell extension it's very difficult to debug. I tried using MessageBoxes and writing to the console but those wouldn't work, so I have added the WriteLog so that I have some idea of what it's doing.
This works on the host machine i.e. a log file is created and it shows the path to the EXE, but no log file is created on the VM.
NOTE: When testing on either machine, I'm installing afresh from the application's MSI. Also note that the host is running Windows 11 and the VM is running Windows 10.
So, why does the same code fail to either run the EXE or create a log file on the VM?
I eventually worked out that the problem was how C# handles strings.
If you read through my problem above you will see that, weirdly the same code worked fine on Windows 11 but not on Windows 10.
The problem was that I was letting the compiler interpret the path string. I had 'escaped' the slashes as shown here and it should have worked fine:
sEXE = "C:\\temp\\AddLocation.exe";
Changing it to the following resolved the problem so that it works on both now:
sEXE = #"C:\temp\AddLocation.exe";
Similarly, whereas it wouldn't create a log file on Win10, changing the path to the log file to the following fixed it:
using (StreamWriter sr = new StreamWriter(#"C:\Temp\ShellExtLog.txt"))
I created a simple C# WPF program, which run various setup of different program by clicking on buttons, so it automates some task when I have to configure PCs.
Initially, I used the function Publish of VS, so when I do changes to the code and deploy again the user click on install update and he has the latest version (fantastic), but this application require admin rights because it install features, create folders such as I wrote above, so I add to my project the app.manifest for running my app with the correct rights. I published again the project, but I got an error, I read that <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> option and ClickOnce can't exists at the same time, I found some workaround but not very functional, below the code:
public MainWindow()
{
InitializeComponent();
AdminRelauncher();
}
private void AdminRelauncher()
{
if (!IsRunAsAdmin())
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Assembly.GetEntryAssembly().CodeBase;
proc.Verb = "runas";
try
{
Process.Start(proc);
Application.Current.Shutdown();
}
catch (Exception ex)
{
MessageBoxResult mess = MessageBox.Show("Program must be run as admin! \n\n" + ex.ToString());
}
}
}
private bool IsRunAsAdmin()
{
try
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch (Exception)
{
return false;
}
}
After that i create a setup using Microsoft VS Installer Projects, it works well but every time I do changes or fixes to the code I have to deploy the setup -> unistall the old program -> install the new, this is a waste of time.
So there is any way to deploy a sort of installer or something else which check for application update?
Or better run as administrator the application installed with ClickOnce?
It is best you create another app, a Launcher, whose purpose is to check if a local file on your other app have a version number below the one stored at your database/ftp. If it is true, then your Launcher will download from your ftp the new version and overwrite the old one. It is like I work on my current C# projects :P
Of course, you can also make your Launcher the main executable, at the end of the update check, it can run your program, and thats all, your users only have to run the launcher to update and/or run your main program.
I have created an application in c# that connects to our QB in order to post invoice ans such. I am ready to deploy this to out accountants so they can further test the application. This app works fine on my machine, however, when I build my project and take the exe to one of our accountants computers I get an error about "COM class factory, blah, blah Class not registered"
In the past that error would mean that I need to build the c# with x86 and not x64, but I did and still receive the error. I now believe that they do not have the QBFC12.dll registered on their computer like I do.
Is this the problem, and if so then do I have to manually register the dll or is their another way to get that dll on their machine?
I found the answer finally.
If you installed QBSDK, explore that folder and locate the Tools folder
Under that you should find a Installers folder that has "QBFC12_0Installer.exe"
Install the exe on the client machine.
Try to run your program, if you encounter another error about "QBXML components are not installed, you will need to re-install QuickBooks and follow from step 1 again. This should get your application up and running for the client.
The person that came the closest and set me on the right track was MikeBr59 so I upvoted him, and posted this incase it helps anyone else.
Thanks,
I think you have to copy it manually and register.
There is no other alternative.
Follow the below steps to copy and register it manually.
1.copy "QBFC12.dll" file into following 2 folders :
a.C:\Windows\System32\
b.C:\Windows\SysWOW64\
2.register the "QBFC12.dll" file using following steps :
open Command Prompt
cd C:\Windows\System32
regsvr32 QBFC12.dll
3.while running the project from visual studio force the platform target as 32 bit -> as the project hasbeen developed in 32 bit using following steps:
Right click on Project
Select Properties
Goto Build Options
Change "Platform Target" from "ANY CPU" to "X86"
4.now run the Project.
Per the QuickBooks SDK docs
You can never redistribute the request processor DLL (qbxmlrp.dll or qbxmlrp2.dll). This violates the license agreement and can lead to undesirable user experiences.
NOTE: It is a violation of your qbXML license agreement to redistribute QBFC, RDS, the QBO connector, or the web connector without using either our stand-alone installers or our merge modules.
To solve this problem, I created the following static class:
public static class QbfcInstaller
{
/// <summary>
/// Installs QBFC if not registered
/// </summary>
public static void install()
{
bool installed = CheckIfInstalled();
if(!installed)
{
string path = #"\\192.168.1.4\App\Publish\QBFC15_0Installer.exe";
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
//This is required in order for the Process to be able to request Elevation
startInfo.UseShellExecute = true;
startInfo.FileName = path;
startInfo.WindowStyle = ProcessWindowStyle.Normal;
//This is required in order for the Process to request Elevation
startInfo.Verb = "runas";
try
{
MessageBox.Show("In order to work properly the application needs to install the Quickbooks Connector Library.\nPlease DO NOT skip this step or it will cause errors latter."
, "Install QBFC 15.0", MessageBoxButtons.OK, MessageBoxIcon.Information);
using(Process installProcess = Process.Start(startInfo))
{
installProcess.WaitForExit();
}
}
catch(Exception ex)
{
MessageBox.Show("Unable to install QBFC Error: " + ex.Message);
Process.GetCurrentProcess().Kill();
}
}
}
/// <summary>
/// Checks if QBFC is registered
/// </summary>
/// <returns></returns>
static bool CheckIfInstalled()
{
try
{
IQBSessionManager sessionManager = new QBSessionManager();
}
catch(Exception ex)
{
if(ex.HResult == -2147221164)
{
return false;
}
}
return true;
}
}
Then, I modified Program.Main() to call QbfcInstaller.install() before starting the Application:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
QbfcInstaller.install();
Application.Run(new FrmLogin());
}
This basically checks if QBFC COM is registered by trying to create a QBSessionMenager. If an error occurs, it checks if ex.Hresult is -2147221164, which is the error that throws if it's not registered. If it's not registered, it then starts the QBFC installer from a local shared folder. (You can also download the installer from a web server and then run it.)
I solved the issue of my x64 application not being able to use QBFC12.dll over COM by creating a COM+ application and registering QBFC12.dll as components of that COM+ application in Windows Component Services.
.Net 3.5
I've built into the service exe the ability for it to install itself using a -i feature. I have a custom installer class and am using a common technique on found online here. That installer class basically has it's own service and serviced process installer.
This code has worked well for a very long time. Finally ran into a Win 7 64 bit machine were it refuses to install.
Basically, the log shows it's installing the service and that succeeds. Then it tries to create an event log and that fails with
An exception occurred during the Install phase.
System.ComponentModel.Win32Exception: The specified service already
exists
I just got done having the OS completely reinstalled from scratch, first thing I did was try to install as a service, and it's the same error. Why is it thinking that event log is already there?
I've already read all the other posts and I've browsed my registry and there is nothing in there for my service or event log. I have full admin rights, when I try to open cmd as administrator, it doesn't even prompt me, so as far as I can tell, I am an admin (I can see that in my user profile).
I even added code to check to see if it found the EventLog using System.Diagnostics.EventLog.SourceExists which does report it found it, and so I added a call to System.Diagnostics.EventLog.DeleteEventSource but that doesn't help.
I even tried removing the EventLog installer from the ServiceInstaller, but then it starts failing for other reasons.
Any ideas?
Here is some sample code for an alternate installer I tried that I found here with the same results:
public partial class Service1Installer : Installer
{
public Service1Installer()
{
InitializeComponent();
ServiceProcessInstaller process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
ServiceInstaller serviceAdmin = new ServiceInstaller();
serviceAdmin.StartType = ServiceStartMode.Manual;
serviceAdmin.ServiceName = "Service1";
serviceAdmin.DisplayName = "Service1";
serviceAdmin.Description = "Service1";
Installers.Add(serviceAdmin);
Installers.Add(process );
}
}
uninstall your service
installutil /u yourproject.exe
restart your machine
http://msdn.microsoft.com/en-us/library/sd8zc8ha(v=vs.80).aspx
let me know if you still have a issue
Use installutil as #MicahArmantrout mentions, if the exe still resides on disk.
Otherwise, open a commandline as Administrator and execute: sc delete "my service name"
In the end, my problem was our internal installer. I commented it out and now just install the service from the command line and it now installs on 64 bit OS. Still don't know why it would work before on 32 bit.